diff --git a/LICENSE b/LICENSE
index c97fe3d..3f8f4cf 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
-MIT License
+GPL3 License
-Copyright (c) 2017–2023 Zach Leatherman @zachleat
+Copyright (c) 2023 Nathan Upchurch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk
index 719dcff..6fb450a 100644
--- a/_includes/layouts/base.njk
+++ b/_includes/layouts/base.njk
@@ -11,13 +11,8 @@
-
{#- Bundle CSS #}
{%- css %}{% include "public/css/index.css" %}{% endcss %}
- {# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
-
- {#- Render the CSS bundle using Inlined CSS (for the fastest site performance in production) #}
-
{%- css %}{% include "public/css/webfonts/webfonts.css" %}{% endcss %}
{%- css %}{% include "public/css/dropcap.css" %}{% endcss %}
@@ -66,9 +61,30 @@
Top level navigation menu
diff --git a/_includes/layouts/baseBareBones.njk b/_includes/layouts/baseBareBones.njk
index 9f2b50e..6207d40 100644
--- a/_includes/layouts/baseBareBones.njk
+++ b/_includes/layouts/baseBareBones.njk
@@ -11,10 +11,6 @@
{#- Bundle CSS #}
{%- css %}{% include "public/css/index.css" %}{% endcss %}
- {# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
-
- {#- Render the CSS bundle using Inlined CSS (for the fastest site performance in production) #}
-
{%- css %}{% include "public/css/webfonts/webfonts.css" %}{% endcss %}
{%- css %}{% include "public/css/dropcap.css" %}{% endcss %}
diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk
index 9d5aa66..6840566 100644
--- a/_includes/layouts/post.njk
+++ b/_includes/layouts/post.njk
@@ -2,8 +2,7 @@
layout: layouts/base.njk
---
{# Only include the syntax highlighter CSS on blog posts #}
-{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
-{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
+{%- css %}{% include "public/css/code.css" %}{% endcss %}
{{ title }}
diff --git a/eleventy.config.js b/eleventy.config.js
index e04c73f..1076e98 100644
--- a/eleventy.config.js
+++ b/eleventy.config.js
@@ -18,17 +18,7 @@ const figoptions = {
};
module.exports = function(eleventyConfig) {
- // Copy the contents of the `public` folder to the output folder
- // For example, `./public/css/` ends up in `_site/css/`
- eleventyConfig.addPassthroughCopy({
- "./public/": "/",
- "./node_modules/prismjs/themes/prism-okaidia.css": "/css/prism-okaidia.css"
- });
- // Run Eleventy when these files change:
- // https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets
-
- // Watch content images for the image pipeline.
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
// App plugins
@@ -92,24 +82,20 @@ module.exports = function(eleventyConfig) {
placement: "after",
class: "header-anchor",
symbol: "#",
- ariaHidden: false,
- }),
- level: [1,2,3,4],
- slugify: eleventyConfig.getFilter("slugify")
- }).use(markdownItFootnote).use(mdfigcaption, figoptions);
- });
-
- // Features to make your build faster (when you need them)
+ ariaHidden: false, // Features to make your build faster (when you need them)
// If your passthrough copy gets heavy and cumbersome, add this line
// to emulate the file copy on the dev server. Learn more:
// https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve
// eleventyConfig.setServerPassthroughCopyBehavior("passthrough");
+ }),
+ level: [1,2,3,4],
+ slugify: eleventyConfig.getFilter("slugify")
+ }).use(markdownItFootnote).use(mdfigcaption, figoptions);
+ });
return {
- // Control which files Eleventy will process
- // e.g.: *.md, *.njk, *.html, *.liquid
templateFormats: [
"md",
"njk",
@@ -117,30 +103,16 @@ module.exports = function(eleventyConfig) {
"liquid",
],
- // Pre-process *.md files with: (default: `liquid`)
markdownTemplateEngine: "njk",
- // Pre-process *.html files with: (default: `liquid`)
htmlTemplateEngine: "njk",
- // These are all optional:
dir: {
input: "content", // default: "."
includes: "../_includes", // default: "_includes"
data: "../_data", // default: "_data"
output: "_site"
},
-
- // -----------------------------------------------------------------
- // Optional items:
- // -----------------------------------------------------------------
-
- // If your site deploys to a subdirectory, change `pathPrefix`.
- // Read more: https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix
-
- // When paired with the HTML plugin https://www.11ty.dev/docs/plugins/html-base/
- // it will transform any absolute URLs in your HTML to include this
- // folder name and does **not** affect where things go in the output folder.
pathPrefix: "/",
};
};
diff --git a/package.json b/package.json
index 1163dd0..b10f40d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
- "name": "eleventy-base-blog",
+ "name": "nathanupchurch.com",
"version": "8.0.0",
- "description": "A starter repository for a blog web site using the Eleventy site generator.",
+ "description": "The personal website and blog of Nathan Upchurch",
"scripts": {
"build": "npx @11ty/eleventy",
"build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/",
@@ -12,25 +12,21 @@
},
"repository": {
"type": "git",
- "url": "git://github.com/11ty/eleventy-base-blog.git"
+ "url": "git://upchur.ch/gitea/n_u/nathanupchurch.com.git"
},
"author": {
- "name": "Zach Leatherman",
- "email": "zachleatherman@gmail.com",
- "url": "https://zachleat.com/"
+ "name": "Nathan Upchurch",
+ "email": "blog@upchur.ch",
+ "url": "https://nathanupchurch.com/"
},
- "license": "MIT",
+ "license": "GPL3",
"engines": {
"node": ">=14"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/11ty"
- },
"bugs": {
- "url": "https://github.com/11ty/eleventy-base-blog/issues"
+ "url": "https://upchur.ch/gitea/n_u/nathanupchurch.com/issues"
},
- "homepage": "https://github.com/11ty/eleventy-base-blog#readme",
+ "homepage": "https://upchur.ch/gitea/n_u/nathanupchurch.com",
"devDependencies": {
"@11ty/eleventy": "^2.0.1",
"@11ty/eleventy-img": "^3.1.0",
@@ -39,7 +35,9 @@
"@11ty/eleventy-plugin-rss": "^1.2.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
"luxon": "^3.3.0",
- "markdown-it-anchor": "^8.6.7"
+ "markdown-it-anchor": "^8.6.7",
+ "markdown-it-footnote": "^3.0.3",
+ "mdfigcaption": "^0.1.1"
},
"dependencies": {
"markdown-it-footnote": "^3.0.3",
diff --git a/public/css/code.css b/public/css/code.css
new file mode 100644
index 0000000..84f974d
--- /dev/null
+++ b/public/css/code.css
@@ -0,0 +1,161 @@
+code[class*="language-"],
+pre[class*="language-"] {
+ color: #f8f8f2;
+ background: none;
+ text-shadow: 0 1px rgba(0, 0, 0, 0.3);
+ font-family: var(--font-family-monospace);
+ font-size: var(--font-n);
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
+
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+ padding: var(--single-gap);
+ margin: .5em 0;
+ overflow: auto;
+ border-radius: 0.3em;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+ background: #272822;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+ padding: .1em;
+ border-radius: .3em;
+ white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: #8292a2;
+}
+
+.token.punctuation {
+ color: #f8f8f2;
+}
+
+.token.namespace {
+ opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.constant,
+.token.symbol,
+.token.deleted {
+ color: #f92672;
+}
+
+.token.boolean,
+.token.number {
+ color: #ae81ff;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+ color: #a6e22e;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string,
+.token.variable {
+ color: #f8f8f2;
+}
+
+.token.atrule,
+.token.attr-value,
+.token.function,
+.token.class-name {
+ color: #e6db74;
+}
+
+.token.keyword {
+ color: #66d9ef;
+}
+
+.token.regex,
+.token.important {
+ color: #fd971f;
+}
+
+.token.important,
+.token.bold {
+ font-weight: bold;
+}
+.token.italic {
+ font-style: italic;
+}
+
+.token.entity {
+ cursor: help;
+}
+
+pre[class*="language-diff-"] {
+ --eleventy-code-padding: 1.25em;
+ padding-left: var(--eleventy-code-padding);
+ padding-right: var(--eleventy-code-padding);
+ font-family: var(--font-family-monospace);
+ font-size: 1em;
+}
+.token.deleted {
+ background-color: hsl(0, 51%, 37%);
+ color: inherit;
+}
+.token.inserted {
+ background-color: hsl(126, 31%, 39%);
+ color: inherit;
+}
+
+/* Make the + and - characters unselectable for copy/paste */
+.token.prefix.unchanged,
+.token.prefix.inserted,
+.token.prefix.deleted {
+ -webkit-user-select: none;
+ user-select: none;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding-top: 2px;
+ padding-bottom: 2px;
+}
+.token.prefix.inserted,
+.token.prefix.deleted {
+ width: var(--eleventy-code-padding);
+ background-color: rgba(0,0,0,.2);
+}
+
+/* Optional: full-width background color */
+.token.inserted:not(.prefix),
+.token.deleted:not(.prefix) {
+ display: block;
+ margin-left: calc(-1 * var(--eleventy-code-padding));
+ margin-right: calc(-1 * var(--eleventy-code-padding));
+ text-decoration: none; /* override del, ins, mark defaults */
+ color: inherit; /* override del, ins, mark defaults */
+}
diff --git a/public/css/dropcap.css b/public/css/dropcap.css
index 275f39e..32ef683 100644
--- a/public/css/dropcap.css
+++ b/public/css/dropcap.css
@@ -1,15 +1,21 @@
main > p:not(.nodropcap):first-of-type:first-letter {
float: left;
- font-size: 4rem;
+ font-size: 3.25rem;
font-weight: 300;
line-height: 60px;
padding: .5rem .5rem .5rem .5rem;
color: var(--contrast-color);
border: solid 2px var(--contrast-color);
- font-family: 'Playfair Display';
+ font-family: var(--font-family-headline);
font-weight: 700;
margin-right: .25em;
border-radius: .2em;
border-top-left-radius: 0;
margin-bottom: -.2em;
}
+
+@media(max-width: 556px) {
+ main > p:not(.nodropcap):first-of-type:first-letter {
+ font-size: 3rem;
+ }
+}
diff --git a/public/css/index.css b/public/css/index.css
index 9cc9f22..2e11b71 100644
--- a/public/css/index.css
+++ b/public/css/index.css
@@ -1,10 +1,11 @@
/* Defaults */
:root {
+ --font-family-headline: 'Playfair Display';
--font-family: Manrope;
--font-family-monospace: Consolas, Menlo, Monaco, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Courier New, Courier, monospace;
}
-/* Tokens */
+/* Design Tokens */
:root {
/* Colors */
--color-gray-20: #e0e0e0;
@@ -15,7 +16,7 @@
--background-color: #FAF5F5;
--text-color: var(--color-gray-90);
- --text-color-link: var(--color-gray-90);
+ --text-color-link: var(--text-color);
--text-color-link-active: rgba(3,144,116,1);
--text-color-link-visited: var(--color-gray-90);
@@ -31,8 +32,25 @@
--pill-radius: 5rem;
--card-radius: .3rem;
- /* Time */
+ /* Spacing */
+ --single-gap: 1rem;
+ --double-gap: 2rem;
+
+ /* Animation Timing */
--transition-time: .3s;
+
+ /* Font Sizes */
+ --font-xxl: 3.75rem;
+ --font-xl: 2rem;
+ --font-l: 1.5rem;
+ --font-n: 1rem;
+ --font-s: .75rem;
+ --font-xs: .65rem;
+
+ /* Font Weights */
+ --weight-extraheavy: 700;
+ --weight-heavy: 500;
+ --weight-normal: 300;
}
@media (prefers-color-scheme: dark) {
@@ -52,6 +70,16 @@
}
}
+@media(max-width: 556px) {
+ :root {
+ /* Font Sizes */
+ --font-xxl: 1.75rem;
+ --font-xl: 1rem;
+ --font-l: 1rem;
+ --font-n: .85rem;
+ }
+}
+
/* Global stylesheet */
* {
box-sizing: border-box;
@@ -62,7 +90,7 @@ body {
padding: 0;
margin: 0 auto;
font-family: var(--font-family);
- font-weight: 300;
+ font-weight: var(--weight-normal);
font-variant-Ligatures: normal;
color: var(--text-color);
background-color: var(--background-color);
@@ -73,14 +101,10 @@ html {
body {
max-width: 40em;
}
-
a {
- text-decoration: wavy underline;
text-decoration-color: var(--contrast-color);
text-decoration-thickness: .1rem;
- text-decoration-skip: none;
transition: all .5s;
- font-weight: 700;
}
/* https://www.a11yproject.com/posts/how-to-hide-content/ */
@@ -95,33 +119,26 @@ a {
}
h1 {
- font-family: 'Playfair Display';
- font-weight: 700;
- font-size: 3.75rem;
+ font-family: var(--font-family-headline);
+ font-weight: var(--weight-extraheavy);
+ font-size: var(--font-xxl);
font-style: normal;
line-height: 4rem;
padding-top: 3rem;
margin-bottom: 0;
}
-@media(max-width: 556px) {
- h1 {
- font-size: 3rem;
- padding-top: 0;
- }
-}
-
p:last-child {
margin-bottom: 0;
}
p, li {
line-height: 1.75;
- font-size: 14pt;
+ font-size: var(--font-n);
}
main > p > img, main > p > a > img {
width: 100%;
- padding-top: 2rem;
+ padding-top: var(--double-gap);
}
figure {
@@ -138,7 +155,7 @@ figure > a > img {
figcaption {
text-align: center;
- padding-top: 1em;
+ padding-top: var(--single-gap);
}
.page-block {
@@ -158,13 +175,13 @@ a[href]:active {
}
main {
- padding: 1rem;
+ padding: var(--single-gap);
}
main h2 {
- font-weight: 700;
- font-size: 2em;
- margin-top: 2em;
+ font-weight: var(--weight-extraheavy);
+ font-size: 2rem;
+ margin-top: var(--double-gap);
}
main :first-child {
@@ -179,7 +196,7 @@ header {
list-style: none;
border-top: 1px solid var(--color-gray-20);
padding: 1em 0;
- margin-top: 2rem;
+ margin-top: var(--double-gap);
}
table {
@@ -221,15 +238,9 @@ header {
align-items: end;
padding: 1em;
}
-@media(max-width: 556px) {
- header {
- padding: 1rem .5rem 1rem .5rem;
- }
-}
-
.home-link {
- font-size: 1em; /* 16px /16 */
- font-weight: 700;
+ font-size: var(--font-n); /* 16px /16 */
+ font-weight: var(--weight-extraheavy);
margin-right: 2em;
display: flex;
align-items: end;
@@ -247,61 +258,59 @@ header {
margin: 0;
list-style: none;
}
+nav ul {
+ display: flex;
+ align-items: end;
+}
.nav-icon {
- max-width: .5rem;
- margin-right: .5rem;
+ width: var(--single-gap);
+ height: .8rem;
+ margin-right: .25rem;
+ fill: var(--color-gray-90);
+ padding-bottom: .3rem;
}
.nav-item {
display: inline-block;
- margin-right: 2em;
+ text-decoration: none;
+}
+.nav-item li {
+ display: flex;
+ align-items: end;
+ height: 2rem;
+ margin-right: .5em;
margin-bottom: 0;
text-transform: uppercase;
- letter-spacing: .2rem;
- font-size: .6rem;
- font-weight: 500;
- background-color: var(--nav-pill-background-color-inactive);
- padding: .55em .85em .55em 1.2em;
- border-radius: .75em;
- color: var(--nav-pill-text-color);
+ letter-spacing: .15rem;
+ font-size: var(--font-xs);
+ font-weight: var(--weight-heavy);
+ color: var(--color-gray-90);
+ border-top: 1px solid var(--color-gray-90);
transition: all .5s;
}
.subscribe:hover {
- background-color: rgba(225,90,0,1);
- color: var(--nav-pill-text-color);
+ color: var(--color-gray-90);
}
.nav-item a[href]:visited {
- color: var(--nav-pill-text-color-link-visited);
+ color: var(--color-gray-90);
}
.nav-item a[href]:hover {
text-decoration: none;
- color: var(--nav-pill-text-color);
+ color: var(--color-gray-90);
}
.nav-item a[href]:not(:hover) {
text-decoration: none;
- color: var(--nav-pill-text-color);
+ color: var(--color-gray-90);
}
.nav-item[data-currentpage="true"] {
- background-color: var(--nav-pill-background-color-active);
}
.nav a[href][aria-current="page"] {
- background-color: var(--nav-pill-background-color-active);
- color: var(--nav-pill-text-color);
-}
-
-@media(max-width: 556px) {
- .nav {
- flex-flow: row wrap;
- }
- .nav-item {
- margin-right: 1rem;
- margin-bottom: .5rem;
- }
+ color: var(--color-gray-90);
}
/* Posts list */
.postlist h2 {
- margin-bottom: 2rem;
+ margin-bottom: var(--double-gap);
}
.postlist-item-container {
display: flex;
@@ -315,28 +324,28 @@ header {
margin-bottom: 1em;
width: 100%;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
- padding: 1rem 1.1rem 1rem 1.1rem;
+ padding: var(--single-gap) 1.1rem var(--single-gap) 1.1rem;
border-radius: var(--card-radius);
background-color: white;
}
.post-image-container {
border-radius: var(--card-radius);
- margin-right: 1rem;
+ margin-right: var(--single-gap);
overflow: hidden;
height: 10em;
}
.postlist-date,
.postlist-item:before {
- font-size: 0.8125em; /* 13px /16 */
+ font-size: var(--font-s); /* 13px /16 */
color: var(--color-gray-90);
}
.postlist-date {
word-spacing: -0.5px;
}
.postlist-link {
- font-size: 1.1875em; /* 19px /16 */
- font-weight: 700;
+ font-size: var(--font-xl); /* 19px /16 */
+ font-weight: var(--weight-extraheavy);
padding-right: .5em;
text-decoration: none;
}
@@ -344,7 +353,7 @@ header {
margin-bottom: 0;
}
.postlist-item-active .postlist-link {
- font-weight: bold;
+ font-weight: var(--weight-extraheavy);
}
.post-copy {
display: flex;
@@ -419,12 +428,12 @@ a.post-tag:hover {
margin: 0em .5em 1.25em 0em;
}
.taglist li a {
- font-size: 1.25rem;
+ font-size: var(--font-l);
text-decoration-color: var(--contrast-color);
text-decoration-thickness: .1rem;
text-decoration-skip: none;
transition: all .5s;
- font-weight: 700;
+ font-weight: var(--weight-extraheavy);
padding: .4rem .8rem .4rem .8rem;
}
.postlist-item > .post-tag {
@@ -444,17 +453,17 @@ a.post-tag:hover {
gap: .5em;
list-style: none;
padding: 0 0 0 .4em;
- font-size: .8em;
+ font-size: var(--font-s);
margin-bottom: 5em;
}
.post-metadata time {
margin-right: .5em;
- font-size: 1em;
+ font-size: var(--font-n);
}
@media(max-width: 556px) {
.post-metadata {
- margin-bottom: 1em;
+ margin-bottom: var(--single-gap);
}
}
@@ -462,7 +471,7 @@ a.post-tag:hover {
.header-anchor {
text-decoration: none;
font-style: normal;
- font-size: 1em;
+ font-size: var(--font-n);
margin-left: .1em;
}
a[href].header-anchor,
@@ -479,5 +488,52 @@ a[href].header-anchor:focus,
}
h2 + .header-anchor {
- font-size: 1.5em;
+ font-size: var(--font-l);
+}
+
+/* Mobile Styles */
+@media(max-width: 556px) {
+ body {
+ padding: 0rem 1.25rem 0rem 1.25rem;
+ }
+ figcaption {
+ font-size: var(--font-n);
+ }
+ h1 {
+ font-size: var(--font-xxl);
+ padding-top: 0;
+ line-height: 2rem;
+ }
+ h2, .postlist h2, main h2 {
+ font-size: var(--font-xl);
+ margin-bottom: var(--single-gap);
+ }
+ h3, .post-copy a h3 {
+ font-size: 1rem;
+ }
+ header {
+ padding: 0rem .5rem var(--single-gap) .5rem;
+ margin-bottom: var(--single-gap);
+ }
+ .home-link {
+ max-width: 1rem;
+ margin-top: var(--single-gap);
+ }
+ .nav {
+ flex-flow: row wrap;
+ }
+ .nav-item {
+ margin-right: .5rem;
+ }
+ p, p.nodropcap.page-block, .post-copy p {
+ font-size: var(--font-n);
+ line-height: 1.25rem;
+ margin-top: var(--single-gap);
+ }
+ .post-metadata time, time.postlist-date {
+ font-size: var(--font-s);
+ }
+ .post-tag, a.post-tag, .taglist li a {
+ font-size: var(--font-xs);
+ }
}
diff --git a/public/css/prism-diff.css b/public/css/prism-diff.css
index 9f7e676..c76aab5 100644
--- a/public/css/prism-diff.css
+++ b/public/css/prism-diff.css
@@ -6,6 +6,8 @@ pre[class*="language-diff-"] {
--eleventy-code-padding: 1.25em;
padding-left: var(--eleventy-code-padding);
padding-right: var(--eleventy-code-padding);
+ font-family: monospace;
+ font-size: var(--font-n);
}
.token.deleted {
background-color: hsl(0, 51%, 37%);