Compare commits
46 Commits
responsive
...
8ad99a35d4
Author | SHA1 | Date | |
---|---|---|---|
8ad99a35d4 | |||
a908843984 | |||
bfdb9f8419 | |||
a7ec4e9335 | |||
c6ea0176a3 | |||
bdcda7f2db | |||
5d475f4bf3 | |||
0fbfbc0b78 | |||
cb8999f50a | |||
d0a1785f23 | |||
f3c58d09da | |||
7095d8850b | |||
0284950ba5 | |||
7754b310c3 | |||
4add841e55 | |||
3ff627cdc8 | |||
b7e997515e | |||
75aa8e4a33 | |||
fb06d54ea5 | |||
cb33208e54 | |||
6328a531a7 | |||
1ba8841d32 | |||
bc18e89d8d | |||
f8610fe915 | |||
b4c2a76949 | |||
a44a1c4431 | |||
5bf446c5c2 | |||
5e324f2afd | |||
dd2c327613 | |||
21b66dd28f | |||
6dc2db4c52 | |||
acb55c80a1 | |||
2cf0c6ce1d | |||
d328e79da9 | |||
34c37f37e1 | |||
3ec15ed8e2 | |||
5389651b27 | |||
afd8a3ca6e | |||
3cf4345042 | |||
c153a2a60d | |||
7c40b754db | |||
4a476a0207 | |||
21377ff19f | |||
092c806226 | |||
c5121f01ca | |||
d64b6e15cd |
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
_site/
|
||||
node_modules/
|
||||
package-lock.json
|
||||
.kateproject.notes
|
||||
|
@@ -1,20 +1,13 @@
|
||||
TODO:
|
||||
|
||||
Integrate est. read time
|
||||
Integrate % done in article
|
||||
Investigate pagination for /blog/
|
||||
Integrate recipe structured data for recipe type articles
|
||||
No line breaks in inline code fences
|
||||
Style inline code fences with background
|
||||
Integrate ins plugin
|
||||
|
||||
Fediring?
|
||||
Add "Now" to RSS feed.
|
||||
|
||||
Performance / Accessibility:
|
||||
---------------------------------------
|
||||
Lazy load images
|
||||
Remove unecessary fonts
|
||||
change font-display to "swap"
|
||||
Caching
|
||||
Add explicit image dimensions?
|
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
GPL3 License
|
||||
|
||||
Copyright (c) 2023 Nathan Upchurch
|
||||
Copyright (c) 2023-2024 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
|
||||
|
@@ -20,6 +20,7 @@ My blog, originally based on the very helpful eleventy-base-blog v8, although it
|
||||
* All blog posts
|
||||
* Each individual tag
|
||||
* /now page that nicely handles posts tagged with "now"
|
||||
* Blogroll generated from _data/blogroll.js, with an automatically updated .opml so that visitors can import every blog in the list
|
||||
|
||||
### Technical
|
||||
* Reusable web components:
|
||||
@@ -27,6 +28,7 @@ My blog, originally based on the very helpful eleventy-base-blog v8, although it
|
||||
* Mastodon comment
|
||||
* Profile picture
|
||||
* Embedded toot
|
||||
* Embed audio
|
||||
|
||||
### Quality of Life
|
||||
* Copyright notice, default post image, alt text, and author details defined in `metadata.js`.
|
||||
@@ -34,4 +36,4 @@ My blog, originally based on the very helpful eleventy-base-blog v8, although it
|
||||
* robots.txt tells AI scrapers to GTFO
|
||||
|
||||
### Weird and Wonderful
|
||||
* [Accessible cowsay output embedding](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki#add-a-cowsay-to-a-post)
|
||||
* [Accessible ~~cowsay~~ cowthink output embedding](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki#add-a-cowsay-to-a-post)
|
||||
|
476
_data/blogroll.js
Normal file
@@ -0,0 +1,476 @@
|
||||
export default {
|
||||
categories: [
|
||||
{
|
||||
name: "Comics",
|
||||
blogs: [
|
||||
{
|
||||
title: "Incidental Comics",
|
||||
feedUrl:
|
||||
"http://www.incidentalcomics.com/feeds/posts/default?alt=rss",
|
||||
url: "http://www.incidentalcomics.com",
|
||||
description: "Nice comics about words, et cetera.",
|
||||
},
|
||||
{
|
||||
title: "XKCD",
|
||||
feedUrl: "https://xkcd.com/rss.xml",
|
||||
url: "https://xkcd.com",
|
||||
description: "Does XKCD needs an introduction?",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Design",
|
||||
blogs: [
|
||||
{
|
||||
title: "Libre Arts",
|
||||
feedUrl: "https://librearts.org/index.xml",
|
||||
url: "https://librearts.org",
|
||||
description: "News on FLOSS creative software.",
|
||||
},
|
||||
{
|
||||
title: "Autumn Kotsiuba",
|
||||
feedUrl: "https://autumnkotsiuba.wixsite.com/portfolio/blog-feed.xml",
|
||||
url: "https://autumnkotsiuba.wixsite.com",
|
||||
description: "Autumn blogs about UX content design.",
|
||||
},
|
||||
{
|
||||
title: "Dave Smyth",
|
||||
feedUrl: "https://davesmyth.com/commonplace-feed",
|
||||
url: "https://davesmyth.com",
|
||||
description:
|
||||
"Dave Smyth is a designer and developer interested in privacy, type and ethics.",
|
||||
},
|
||||
{
|
||||
title: "Grumpy Website",
|
||||
feedUrl: "https://grumpy.website/feed.xml",
|
||||
url: "https://grumpy.website",
|
||||
description: "Grumpy takes on UI mistakes.",
|
||||
},
|
||||
{
|
||||
title: "PRINT Magazine",
|
||||
feedUrl: "https://www.printmag.com/feed/",
|
||||
url: "https://www.printmag.com/",
|
||||
description:
|
||||
"Where creative people gather to inspire and build design dialogue.",
|
||||
},
|
||||
{
|
||||
title: "TypeOff.",
|
||||
feedUrl: "https://www.typeoff.de/rss",
|
||||
url: "https://www.typeoff.de",
|
||||
description:
|
||||
"A blog from Dan Reynolds, a design researcher based in Wuppertal, Germany.",
|
||||
},
|
||||
{
|
||||
title: "UX Daily",
|
||||
feedUrl: "https://www.interaction-design.org/rss/site_news.xml",
|
||||
url: "https://www.interaction-design.org",
|
||||
description: "The World’s Largest Free Online Resource on UX Design ",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Food & Beverage",
|
||||
blogs: [
|
||||
{
|
||||
title: "Cocktail Doodle",
|
||||
feedUrl: "https://cocktaildoodle.substack.com/feed",
|
||||
url: "https://cocktaildoodle.substack.com",
|
||||
description:
|
||||
"A charming (but perhaps abandoned) blog from cocktail expert Luke Andrews.",
|
||||
},
|
||||
{
|
||||
title: "Sarah's Vegan Kitchen",
|
||||
feedUrl: "https://sarahsvegankitchen.com/feed/",
|
||||
url: "https://sarahsvegankitchen.com",
|
||||
description:
|
||||
"Sarah has years of recipes including complex staples like vegan cultured butter.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "General Interest",
|
||||
blogs: [
|
||||
{
|
||||
title: "Big Think",
|
||||
feedUrl: "https://bigthink.com/feed",
|
||||
url: "https://bigthink.com",
|
||||
description: "Big thoughts on big issues.",
|
||||
},
|
||||
{
|
||||
title: "Clients from Hell",
|
||||
feedUrl: "https://notalwaysright.com/tag/clients-from-hell/feed",
|
||||
url: "https://notalwaysright.com/tag/clients-from-hell",
|
||||
description:
|
||||
"Cathartic stories about clients behaving badly from notalwaysright.com.",
|
||||
},
|
||||
{
|
||||
title: "kottke.org",
|
||||
feedUrl: "https://feeds.kottke.org/main",
|
||||
url: "https://kottke.org",
|
||||
description: "Home of fine hypertext products since 1998.",
|
||||
},
|
||||
{
|
||||
title: "Neatorama",
|
||||
feedUrl: "https://www.neatorama.com/feed",
|
||||
url: "https://www.neatorama.com/",
|
||||
description: "Yep, Neatorama's still around!",
|
||||
},
|
||||
{
|
||||
title: "The Reframe",
|
||||
feedUrl: "https://www.the-reframe.com/rss/",
|
||||
url: "https://www.the-reframe.com/",
|
||||
description:
|
||||
"Essays on politics and narrative fiction from A.R. Moxon.",
|
||||
},
|
||||
{
|
||||
title: "Webcurios",
|
||||
feedUrl: "https://webcurios.co.uk/feed",
|
||||
url: "https://webcurios.co.uk",
|
||||
description:
|
||||
"A regular(-ish) newsletterblogtypething all about stuff on the internet that its author finds interesting and thinks you might too.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Health",
|
||||
blogs: [
|
||||
{
|
||||
title: "ADDitude",
|
||||
feedUrl: "https://www.additudemag.com/feed/",
|
||||
url: "https://www.additudemag.com/",
|
||||
description:
|
||||
"The world’s most trusted resource for families and adults living with ADHD and related conditions, and for the professionals who work with them.",
|
||||
},
|
||||
{
|
||||
title: "The Gauntlet",
|
||||
feedUrl: "https://www.thegauntlet.news/feed",
|
||||
url: "https://www.thegauntlet.news",
|
||||
description:
|
||||
"A newsletter covering the current science on, and commentary related to, the unmitigated spread of COVID.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Incense, Fragrance, and Perfumery",
|
||||
blogs: [
|
||||
{
|
||||
title: "Apothecary's Garden Blog",
|
||||
feedUrl: "https://apothecarysgarden.com/blogs/blog.atom",
|
||||
url: "https://apothecarysgarden.com/blogs/blog",
|
||||
description:
|
||||
"Explore the world of natural aromatics, and the communities that bring them to us",
|
||||
},
|
||||
{
|
||||
title: "Ayala Moriel Parfums - SmellyBlog",
|
||||
feedUrl: "https://ayalamoriel.com/blogs/smellyblog.atom",
|
||||
url: "https://ayalamoriel.com/blogs/smellyblog",
|
||||
description:
|
||||
"Ayala Moriel Parfums is an independent artisan perfume house dedicated to the art of natural perfumery.",
|
||||
},
|
||||
{
|
||||
title: "A whiff of Ambrosia",
|
||||
feedUrl: "https://whiffofambrosia.wordpress.com/feed/",
|
||||
url: "https://whiffofambrosia.wordpress.com/",
|
||||
description: "Incense reviews and more. (Abandoned?)",
|
||||
},
|
||||
{
|
||||
title: "Dr. Incense",
|
||||
feedUrl: "https://dr-incense.com/blogs/dr-incense-blog.atom",
|
||||
url: "https://dr-incense.com/blogs/dr-incense-blog",
|
||||
description:
|
||||
"Traditional incense maker and founder of the Incense Culture Association of Singapore, and Nanyang Culture Academy.",
|
||||
},
|
||||
{
|
||||
title: "Glass Petal Smoke",
|
||||
feedUrl: "https://glasspetalsmoke.blogspot.com/feeds/posts/default",
|
||||
url: "https://glasspetalsmoke.blogspot.com/",
|
||||
description:
|
||||
"Decoder of flavors and fragrances. Creator of Smell & Tell programming.",
|
||||
},
|
||||
{
|
||||
title: "Incense In The Wind",
|
||||
feedUrl: "https://incenseinthewind.blogspot.com/feeds/posts/default",
|
||||
url: "https://incenseinthewind.blogspot.com/",
|
||||
description: "Incense reviews, rankings, and information.",
|
||||
},
|
||||
{
|
||||
title: "Kikoh Incense",
|
||||
feedUrl: "https://kikohincense.com/blogs/news.atom",
|
||||
url: "https://kikohincense.com/blogs/news",
|
||||
description:
|
||||
"Detailed descriptions of incense listening sessions from the Kikoh Incense web store.",
|
||||
},
|
||||
{
|
||||
title: "KyaraZen",
|
||||
feedUrl: "https://www.kyarazen.com/feed/",
|
||||
url: "https://www.kyarazen.com/",
|
||||
description:
|
||||
"Very informative (but perhaps abandoned) blog from world-renowned incense maker KyaraZen.",
|
||||
},
|
||||
{
|
||||
title: "Olfactory Rescue Service",
|
||||
feedUrl: "https://olfactoryrescueservice.wordpress.com/feed",
|
||||
url: "https://olfactoryrescueservice.wordpress.com",
|
||||
description:
|
||||
"The ultimate retail incense resource providing incense writing and reviews.",
|
||||
},
|
||||
{
|
||||
title: "Ratnagandh",
|
||||
feedUrl: "https://ratnagandh.wordpress.com/feed/",
|
||||
url: "https://ratnagandh.wordpress.com/",
|
||||
description: "Short incense reviews.",
|
||||
},
|
||||
{
|
||||
title: "Rauchfahne",
|
||||
feedUrl: "https://blog.rauchfahne.de/en/feed/",
|
||||
url: "https://blog.rauchfahne.de/en/",
|
||||
description:
|
||||
"Incense reviews and writing in German and English from incense maker, enthusiast, and industry insider Irene.",
|
||||
},
|
||||
{
|
||||
title: "Reed's Handmade Incense Blog",
|
||||
feedUrl: "https://reedshandmadeincense.com/blog/feed/",
|
||||
url: "https://reedshandmadeincense.com/blog/",
|
||||
description:
|
||||
"Writing on incense, tea, and other topics from the Reed's Handmade Incense web store.",
|
||||
},
|
||||
{
|
||||
title: "The Parfum Apothecary - Learning & Culture",
|
||||
feedUrl:
|
||||
"https://www.theparfumapothecary.com/blogs/learning-culture.atom",
|
||||
url: "https://www.theparfumapothecary.com/blogs/learning-culture",
|
||||
description: "Writing on perfume and its history. (Abandoned?)",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "News",
|
||||
blogs: [
|
||||
{
|
||||
title: "openDemocracy",
|
||||
feedUrl: "https://www.opendemocracy.net/en/feed",
|
||||
url: "https://www.opendemocracy.net/",
|
||||
description:
|
||||
"High-quality journalism which challenges power, inspires change and builds leadership among groups underrepresented in the media.",
|
||||
},
|
||||
{
|
||||
title: "Techdirt",
|
||||
feedUrl: "https://www.techdirt.com/feed/",
|
||||
url: "https://www.techdirt.com/feed",
|
||||
description:
|
||||
"Started in 1997 by Floor64 founder Mike Masnick and then growing into a group blogging effort, the Techdirt blog relies on a proven economic framework to analyze and offer insight into news stories about changes in government policy, technology and legal issues that affect companies’ ability to innovate and grow.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Personal Blogs",
|
||||
blogs: [
|
||||
{
|
||||
title: "Andy Bell",
|
||||
feedUrl: "https://andy-bell.co.uk/feed.xml",
|
||||
url: "https://andy-bell.co.uk",
|
||||
description:
|
||||
"Designer, front-end developer and the founder of Set Studio and Piccalilli.",
|
||||
},
|
||||
{
|
||||
title: "Darek Kay",
|
||||
feedUrl: "https://darekkay.com/atom.xml",
|
||||
url: "https://darekkay.com",
|
||||
description:
|
||||
"Front-end developer and an accessibility advocate, currently working at IBM.",
|
||||
},
|
||||
{
|
||||
title: "Ellie Kennard",
|
||||
feedUrl: "https://www.elliekennard.ca/feed",
|
||||
url: "https://www.elliekennard.ca",
|
||||
description: "Photography and thoughts in story form.",
|
||||
},
|
||||
{
|
||||
title: "Garbage Collector",
|
||||
feedUrl: "https://blog.zedas.fr/index.xml",
|
||||
url: "https://zedas.fr/",
|
||||
description:
|
||||
"The little space of a writer, tinkerer, and a coffee addict.",
|
||||
},
|
||||
{
|
||||
title: "Later On",
|
||||
feedUrl: "https://leisureguy.ca/rss",
|
||||
url: "https://leisureguy.ca",
|
||||
description:
|
||||
"Writing on wet shaving, politics, whole food plant based diets, and more.",
|
||||
},
|
||||
{
|
||||
title: "Luke Andrews",
|
||||
feedUrl: "https://world.hey.com/lukeandrews/feed.atom",
|
||||
url: "https://world.hey.com/lukeandrews",
|
||||
description: "A sparse (abandoned?) blog from Luke Andrews.",
|
||||
},
|
||||
{
|
||||
title: "MediaActivist",
|
||||
feedUrl: "https://www.mediaactivist.com/rss/",
|
||||
url: "https://www.mediaactivist.com/",
|
||||
description:
|
||||
"The website of Jay Baker (they/he), a long-time guerrilla journalist and documentarian.",
|
||||
},
|
||||
{
|
||||
title: "Ploum.net",
|
||||
feedUrl: "https://ploum.net/atom_en.xml",
|
||||
url: "https://ploum.net/index_en.html",
|
||||
description:
|
||||
"Writing on tech and free / libre and open source philosophy.",
|
||||
},
|
||||
{
|
||||
title: "Rosnovsky Park",
|
||||
feedUrl: "https://rosnovsky.us/feed/feed.xml",
|
||||
url: "https://rosnovsky.us/",
|
||||
description:
|
||||
"Writing on web development, hiking, and random hobbies from the venerable benefactor, founder, and admin of the lounge.town Mastodon instance.",
|
||||
},
|
||||
{
|
||||
title: "Simone",
|
||||
feedUrl: "https://simone.org/rss",
|
||||
url: "https://simone.org/",
|
||||
description:
|
||||
"Explore modern life via thought-provoking essays, pictures, and conversations.",
|
||||
},
|
||||
{
|
||||
title: "Steven Kennard : Turned Art, Sculpture and Photography",
|
||||
feedUrl: "https://stevenkennard.com/blog/rss",
|
||||
url: "https://stevenkennard.com/blog",
|
||||
description:
|
||||
"Steven Kennard is a woodturner, sculptor and photographer living and working in Nova Scotia, Canada.",
|
||||
},
|
||||
{
|
||||
title: "Stories by Ellen Feinberg",
|
||||
feedUrl: "https://ellensusie59.medium.com/feed",
|
||||
url: "https://ellensusie59.medium.com",
|
||||
description: "Uptown Chicago gal. Irreverent/Irrelevant/Sarcastic.",
|
||||
},
|
||||
{
|
||||
title: "Thefoggiest.dev",
|
||||
feedUrl: "https://thefoggiest.dev/feed",
|
||||
url: "https://thefoggiest.dev",
|
||||
description: "The personal blog of Diederick de Vries of Amsterdam.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Politics",
|
||||
blogs: [
|
||||
{
|
||||
title: "Kevin Drum",
|
||||
feedUrl: "https://jabberwocking.com/feed/",
|
||||
url: "https://jabberwocking.com/",
|
||||
description:
|
||||
"Political blogger and writer, formerly for the Washington Monthly and Mother Jones magazine, now on my own.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Tech",
|
||||
blogs: [
|
||||
{
|
||||
title: "9to5Linux",
|
||||
feedUrl: "https://9to5linux.com/rss",
|
||||
url: "https://9to5linux.com/",
|
||||
description: "Linux news, reviews, tutorials, and more",
|
||||
},
|
||||
{
|
||||
title: "It's FOSS",
|
||||
feedUrl: "https://itsfoss.com/feed/",
|
||||
url: "https://itsfoss.com/",
|
||||
description: "Making You a Better Linux User.",
|
||||
},
|
||||
{
|
||||
title: "LinuxInsider",
|
||||
feedUrl: "https://www.linuxinsider.com?rss=1",
|
||||
url: "https://www.linuxinsider.com",
|
||||
description: "Linux News & Information From Around the World.",
|
||||
},
|
||||
{
|
||||
title: "LOW←TECH MAGAZINE",
|
||||
feedUrl: "https://solar.lowtechmagazine.com/posts/index.xml",
|
||||
url: "https://solar.lowtechmagazine.com/posts/",
|
||||
description:
|
||||
"This is a solar-powered website, which means it sometimes goes offline.",
|
||||
},
|
||||
{
|
||||
title: "Planet KDE",
|
||||
feedUrl: "https://planet.kde.org/global/atom.xml",
|
||||
url: "https://planet.kde.org/",
|
||||
description:
|
||||
"A feed aggregator that collects what the contributors to the KDE community are writing on their respective blogs.",
|
||||
},
|
||||
{
|
||||
title: "Pluralistic",
|
||||
feedUrl: "https://pluralistic.net/feed/",
|
||||
url: "https://pluralistic.net/",
|
||||
description: "Daily links from Cory Doctorow",
|
||||
},
|
||||
{
|
||||
title: "TorrentFreak",
|
||||
feedUrl: "http://torrentfreak.com/feed",
|
||||
url: "http://torrentfreak.com/",
|
||||
description: "Breaking File-sharing, Copyright and Privacy News.",
|
||||
},
|
||||
{
|
||||
title: "Werd I/O",
|
||||
feedUrl: "https://werd.io/feed",
|
||||
url: "https://werd.io",
|
||||
description:
|
||||
"Writing at the intersection of technology, democracy, and society by Ben Werdmuller.",
|
||||
},
|
||||
{
|
||||
title: "We Distribute",
|
||||
feedUrl: "https://wedistribute.org/rss",
|
||||
url: "https://wedistribute.org",
|
||||
description: "Connecting threads across the Web.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Veganism",
|
||||
blogs: [
|
||||
{
|
||||
title: "Vegan Horizon",
|
||||
feedUrl: "https://veganhorizon.substack.com/feed",
|
||||
url: "https://veganhorizon.substack.com",
|
||||
description:
|
||||
"The vegan newsletter you've been waiting for! Brave, disruptive, to the point.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Web Development",
|
||||
blogs: [
|
||||
{
|
||||
title: "CSS Tricks",
|
||||
feedUrl: "https://css-tricks.com/feed",
|
||||
url: "https://css-tricks.com",
|
||||
description:
|
||||
"Tips, Tricks, and Techniques on using Cascading Style Sheets.",
|
||||
},
|
||||
{
|
||||
title: "Chris Coyier",
|
||||
feedUrl: "https://chriscoyier.net/feed/",
|
||||
url: "https://chriscoyier.net",
|
||||
description: "Web craftsman, blogger, author, speaker.",
|
||||
},
|
||||
{
|
||||
title: "Jim Nielsen’s Blog",
|
||||
feedUrl: "https://blog.jim-nielsen.com/feed.xml",
|
||||
url: "https://blog.jim-nielsen.com",
|
||||
description:
|
||||
"20+ years at the intersection of design & code on the web.",
|
||||
},
|
||||
{
|
||||
title: "Own Your Web",
|
||||
feedUrl: "https://buttondown.email/ownyourweb/rss",
|
||||
url: "https://buttondown.com/ownyourweb",
|
||||
description:
|
||||
"A newsletter by Matthias Ott about designing, building, creating, and publishing for and on the Web.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
@@ -3,16 +3,20 @@ export default {
|
||||
logo: "/img/logo.svg",
|
||||
url: "https://nathanupchurch.com/",
|
||||
language: "en",
|
||||
description: "The personal website and blog of Nathan Upchurch.",
|
||||
description:
|
||||
"The personal website and blog of Nathan Upchurch, where I write about incense, free and open source software, design, vegan cooking, music, and all sorts of other topics that I find interesting.",
|
||||
author: {
|
||||
givenName: "Nathan",
|
||||
familyName: "Upchurch",
|
||||
name: "Nathan Upchurch",
|
||||
email: "blog@upchur.ch",
|
||||
url: "https://nathanupchurch.com/me",
|
||||
profilePic: "/img/CN20191025_301_Srt_SQUARE_crop.jpg"
|
||||
profilePic: "/img/CN20191025_301_Srt_SQUARE_crop.jpg",
|
||||
},
|
||||
blogrollUrl: "/blogroll/nathanUpchurchBlogroll.opml",
|
||||
copyrightNotice: "© Nathan Upchurch 2022 - 2024",
|
||||
defaultPostImageURL: "/img/vasilina-sirotina-1NMPvajSt9Q-unsplash_copy.avif",
|
||||
defaultPostImageAlt: "The default post image: a close picture of the dark green leaves of a plant.",
|
||||
defaultPostImageURL: "/img/logo_post.svg",
|
||||
defaultPostImageAlt: "The logo for this blog: a capital letter N.",
|
||||
mastodonHost: "lounge.town",
|
||||
mastodonUser: "nathanu",
|
||||
postlistHeaderText: "Latest posts from the blog:",
|
||||
@@ -21,70 +25,70 @@ export default {
|
||||
title: "My Blog",
|
||||
linkURL: "https://nathanupchurch.com",
|
||||
linkDisplay: "My Blog",
|
||||
iconURL: "/img/logo.svg"
|
||||
iconURL: "/img/logo.svg",
|
||||
},
|
||||
{
|
||||
title: "Mastodon",
|
||||
linkURL: "https://lounge.town/@nathanu",
|
||||
customAttribute: `rel="me"`,
|
||||
linkDisplay: "Mastodon",
|
||||
iconURL: "/img/mastodon.svg"
|
||||
iconURL: "/img/mastodon.svg",
|
||||
},
|
||||
{
|
||||
title: "Email Me",
|
||||
linkURL: "Mailto:blog@upchur.ch",
|
||||
linkDisplay: "Email",
|
||||
iconURL: "/img/envelope.svg"
|
||||
iconURL: "/img/envelope.svg",
|
||||
},
|
||||
{
|
||||
title: "Matrix",
|
||||
linkURL: "https://matrix.to/#/@nathanu:matrix.org",
|
||||
linkURL: "https://matrix.to/#/@nathan:upchur.ch",
|
||||
linkDisplay: "Matrix",
|
||||
iconURL: "/img/matrix-org.svg"
|
||||
iconURL: "/img/matrix-org.svg",
|
||||
},
|
||||
{
|
||||
title: "BookWyrm",
|
||||
linkURL: "https://ramblingreaders.org/user/NathanU",
|
||||
linkDisplay: "BookWyrm",
|
||||
iconURL: "/img/book.svg"
|
||||
iconURL: "/img/book.svg",
|
||||
},
|
||||
{
|
||||
title: "Pixelfed",
|
||||
linkURL: "https://pixelfed.social/@nathanu",
|
||||
linkDisplay: "Pixelfed",
|
||||
iconURL: "/img/pixelfed.svg"
|
||||
iconURL: "/img/pixelfed.svg",
|
||||
},
|
||||
{
|
||||
title: "Lemmy",
|
||||
linkURL: "https://lemmy.ml/u/NathanUp",
|
||||
linkDisplay: "Lemmy",
|
||||
iconURL: "/img/Lemmy_logo.svg"
|
||||
iconURL: "/img/Lemmy_logo.svg",
|
||||
},
|
||||
{
|
||||
title: "PeerTube",
|
||||
linkURL: "https://dalek.zone/a/nathan_upchurch/",
|
||||
linkDisplay: "PeerTube",
|
||||
iconURL: "/img/peertube.svg"
|
||||
iconURL: "/img/peertube.svg",
|
||||
},
|
||||
{
|
||||
title: "Keyoxide Identity Profile",
|
||||
linkURL: "https://keyoxide.org/31E809FAEA1532AC91BBDCF1EC499D3513F69340",
|
||||
linkDisplay: "Keyoxide Identity Profile",
|
||||
iconURL: "/img/keyoxide.svg"
|
||||
}
|
||||
iconURL: "/img/keyoxide.svg",
|
||||
},
|
||||
],
|
||||
webrings: [
|
||||
{
|
||||
name: "Fediring",
|
||||
ringURL: "https://fediring.net/",
|
||||
previousURL: "https://fediring.net/previous?host=nathanupchurch.com",
|
||||
nextURL: "https://fediring.net/next?host=nathanupchurch.com"
|
||||
nextURL: "https://fediring.net/next?host=nathanupchurch.com",
|
||||
},
|
||||
{
|
||||
name: "Geekring",
|
||||
ringURL: "https://geekring.net/",
|
||||
previousURL: "http://geekring.net/site/350/previous",
|
||||
nextURL: "http://geekring.net/site/350/next"
|
||||
}
|
||||
]
|
||||
}
|
||||
nextURL: "http://geekring.net/site/350/next",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@@ -9,5 +9,7 @@
|
||||
{% if webring.nextURL %}<a href="{{ webring.nextURL }}">→</a>{% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% endif %}</p>
|
||||
{% endif %}
|
||||
<a href="/sitemap/">Sitemap</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
21
_includes/layouts/base_full_width_text.njk
Normal file
@@ -0,0 +1,21 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ metadata.language }}">
|
||||
<head>
|
||||
{% include "metadata.njk" %}
|
||||
{#- Bundle CSS #}
|
||||
{%- css %}{% include "public/css/index.css" %}{% endcss %}
|
||||
{%- css %}{% include "public/css/webfonts/webfonts.css" %}{% endcss %}
|
||||
<style>{% getBundle "css" %}</style>
|
||||
{% include "structuredData.njk" %}
|
||||
{% include "umami.html" %}
|
||||
</head>
|
||||
<body>
|
||||
{% include "header.njk" %}
|
||||
<main id="skip">
|
||||
<section class="full-width-text">
|
||||
{{ content | safe }}
|
||||
</section>
|
||||
</main>
|
||||
{% include "footer.njk" %}
|
||||
</body>
|
||||
</html>
|
@@ -3,6 +3,6 @@ layout: layouts/base.njk
|
||||
showPostListHeader: yep
|
||||
---
|
||||
<h1>Hi there, friend.</h1>
|
||||
<p class="nodropcap page-block">My name is Nathan Upchurch. Welcome to my personal website and blog, where I write about <a href="./tags/incense/">incense,</a> <a href="./tags/foss-floss/">free and open source software,</a> design, <a href="./tags/vegan-cooking/">vegan cooking,</a> music, and all sorts of <a href="/tags">other topics</a> that I find interesting. Learn more <a href="about">about me,</a> see <a href="now">what I’ve been up to lately,</a> or have a look at my latest blog posts below.</p>
|
||||
<p class="nodropcap page-block">My name is Nathan Upchurch. Welcome to my personal website and blog, where I write about <a href="./tags/incense/">incense</a>, <a href="./tags/foss-floss/">free and open source software</a>, design, <a href="./tags/vegan-cooking/">vegan cooking</a>, music, and all sorts of <a href="/tags">other topics</a> that I find interesting. Learn more <a href="about">about me</a>, see <a href="now">what I’ve been up to lately</a>, or have a look at my latest blog posts below.</p>
|
||||
|
||||
{{ content | safe }}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
---
|
||||
layout: layouts/baseBareBones.njk
|
||||
hideNav: please
|
||||
---
|
||||
{%- css %}{% include "public/css/me.css" %}{% endcss %}
|
||||
<div class="links-container">
|
||||
|
@@ -13,7 +13,7 @@ layout: layouts/base.njk
|
||||
{% endif %}
|
||||
<div class="post-metadata-copy">
|
||||
<p>{% if author.url %}<a href="{{ author.url }}">{% endif %}
|
||||
{% if author.name %}{{ author.name }}, {% endif %}{% if author.url %}</a>{% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
|
||||
{% if author.name %}{{ author.name }}{% endif %}{% if author.url %}</a>, {% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
|
||||
|
||||
{% else %}
|
||||
{% if metadata.author.profilePic %}
|
||||
@@ -21,7 +21,7 @@ layout: layouts/base.njk
|
||||
{% endif %}
|
||||
<div class="post-metadata-copy">
|
||||
<p>{% if metadata.author.url %}<a href="{{ metadata.author.url }}">{% endif %}
|
||||
{% if metadata.author.name %}{{ metadata.author.name }}, {% endif %}{% if metadata.author.url %}</a>{% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
|
||||
{% if metadata.author.name %}{{ metadata.author.name }}{% endif %}{% if metadata.author.url %}</a>, {% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ title or metadata.title }}</title>
|
||||
<link rel="icon" type="image/x-icon" href="/img/logo_favicon.svg">
|
||||
<link rel="blogroll" type="text/xml" href="{{ metadata.blogrollUrl }}">
|
||||
<meta name="description" content="{{ description or metadata.description }}">
|
||||
<meta name="robots" content="noai, noimageai">
|
||||
<meta name="generator" content="{{ eleventy.generator }}">
|
||||
|
@@ -2,14 +2,9 @@
|
||||
<h2 class="visually-hidden">Top level navigation menu</h2>
|
||||
<ul class="nav">
|
||||
{%- for entry in collections.all | eleventyNavigation %}
|
||||
<a class="nav-item" href="{{ entry.url }}"{% if entry.url == page.url %} aria-current="page" data-currentpage="true"{% endif %}>
|
||||
<li>{{ entry.title }}</li>
|
||||
</a>
|
||||
<li class="nav-item" {% if entry.url == page.url %} aria-current="page" data-currentpage="true"{% endif %}><a href="{{ entry.url }}">{{ entry.title }}</a></li>
|
||||
{%- endfor %}
|
||||
<a class="nav-item" href="/feed/feed.xml">
|
||||
<li class="subscribe">
|
||||
{% include "rssLogo.njk" %}Feed
|
||||
<li class="subscribe nav-item"><a href="/feed/feed.xml">{% include "rssLogo.njk" %}Feed</a>
|
||||
</li>
|
||||
</a>
|
||||
</ul>
|
||||
</nav>
|
||||
|
@@ -3,17 +3,23 @@
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org/",
|
||||
"@type": "Article",
|
||||
"headline": "{{ title }}",
|
||||
"@type": "BlogPosting",
|
||||
"articleBody": "{{ content | striptags }}"
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "{{ metadata.author.name }}"
|
||||
"familyName": "{{ metadata.author.familyName }}",
|
||||
"givenName": "{{ metadata.author.givenName }}",
|
||||
"image": "{{ metadata.url }}{{ metadata.author.profilePic }}",
|
||||
"name": "{{ metadata.author.name }}",
|
||||
"url": "{{ metadata.author.url }}"
|
||||
},
|
||||
"datePublished": "{{ date }}",
|
||||
"description": "{% if synopsis %}{{ synopsis}}{% endif %}",
|
||||
"headline": "{{ title }}",
|
||||
"image": "{% if imageURL %}{{ imageURL | htmlBaseUrl(metadata.url) }}{% else %}{{ metadata.defaultPostImageURL | htmlBaseUrl(metadata.url) }}{% endif %}",
|
||||
"inLanguage": "{{ metadata.language }}",
|
||||
"name": "{{ title }}",
|
||||
"url": "{{ page.url | htmlBaseUrl(metadata.url) }}",
|
||||
"articleBody": "{{ content | striptags }}"
|
||||
}
|
||||
</script>
|
||||
<!-- Open Graph -->
|
||||
|
11
content/about/colophon/index.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
layout: layouts/base_full_width_text.njk
|
||||
---
|
||||
|
||||
# Colophon
|
||||
|
||||
I built this website using [the 11ty static site generator](https://www.11ty.dev/), free and open source variable typefaces [Fraunces](https://fraunces.undercase.xyz/)[^1] and [Manrope](https://www.gent.media/manrope)[^2], and plain-old HTML, CSS, with some vanilla JavaScript for the web components that I built to handle comments. I used the handy calculators on [utopia.fyi](https://utopia.fyi)[^3] to help me implement fluid typography and spacing. [Here's the repo](https://upchur.ch/gitea/n_u/nathanupchurch.com) in case you'd like to have a look at the source.
|
||||
|
||||
[^1]: Designed by Phaedra Charles and Flavia Zimbardi, with contributions by Ethan Cohen, and Andy Clymer.
|
||||
[^2]: Designed by Mikhail Sharanda with thanks to Mirko Velimirovic for contribution.
|
||||
[^3]: Created by James Gilyead & Trys Mudford.
|
@@ -5,18 +5,19 @@ eleventyNavigation:
|
||||
order: 3
|
||||
---
|
||||
<article>
|
||||
<h1>About me and this website I’ve built.</h1>
|
||||
<p>I’m a prolific vegan home cook, classical trombonist, a <abbr title="Free/Libre Open Source Software">FLOSS</abbr> enthusiast, daily GNU/Linux user and unabashed <a href="https://kde.org/">KDE</a> stan, speaker of subpar elementary Spanish, incense maker and appreciator, writer, electronics hobbyist, designer, programmer, music producer, print lover, and human with too many interests and too little time.</p>
|
||||
<h1>About me and my website.</h1>
|
||||
<p class="page-block nodropcap">I’m a prolific vegan home cook, classical trombonist, incense maker, a <abbr title="Free/Libre Open Source Software">FLOSS</abbr> enthusiast, daily GNU/Linux user and unabashed <a href="https://kde.org/">KDE</a> stan, designer, programmer, music producer, print lover, and human with too many interests and too little time. This is my little corner of the internet where I talk about whatever I like without worrying about maintaining a ‘personal brand’, or constraining subject matter to topics which might help advance my career or establish me as a ‘thought leader’. I’m here to express myself and have fun writing about topics I enjoy. If you’d like to learn more about my professional accomplishments and work, I’ll link my professional website here when I get around to it.</p>
|
||||
|
||||
<p>This is my personal website and blog, a little corner of the internet where I can talk about whatever I like without worrying about maintaining a ‘personal brand’, or constraining subject matter to those topics which might help advance my career or establish me as a ‘thought leader’. I’m here to express myself as a human and have fun writing about topics I enjoy. If you’d like to learn more about my professional accomplishments and work, I’ll link my professional website here soon.</p>
|
||||
<a href="./colophon/">
|
||||
<button type="button">Colophon »</button>
|
||||
</a>
|
||||
|
||||
<h2>About this website</h2>
|
||||
<p>This website is made with <a href="https://www.11ty.dev/">the 11ty static site generator</a>, free and open source variable typefaces <a href="https://fraunces.undercase.xyz/">Fraunces</a> and <a href="https://www.gent.media/manrope">Manrope</a>, along with plain-old HTML, CSS, and some vanilla JavaScript for the web components that I built to handle comments. I used the handy calculators on <a href="https://utopia.fyi">utopia.fyi</a> to help me implement fluid typography and spacing.</p>
|
||||
<a href="../me/">
|
||||
<button type="button">Contact »</button>
|
||||
</a>
|
||||
|
||||
<p>I don’t collect any of your personal information, full-stop. All webfonts, icons, and images are hosted locally (these things can sometimes be used to <a href="https://www.firstpost.com/world/how-google-uses-fonts-to-track-what-users-do-online-and-sell-data-to-advertisers-12496552.html">track people across the internet</a> otherwise). I use <a href="https://umami.is/">umami</a>, an open source, privacy-respecting analytics tool, to see how many people visit this website.</p>
|
||||
<a href="./privacy/">
|
||||
<button type="button">Privacy »</button>
|
||||
</a>
|
||||
|
||||
<p>Miss when the internet was fun? Find more interesting personal blogs at <a href="https://blogroll.org">blogroll.org</a>, <a href="https://ooh.directory/">ooh.directory</a>, or surf through the webrings at the bottom of the page.</p>
|
||||
|
||||
<h2>Contact Me</h2>
|
||||
<p>If you would like to say something nice, ask a question, or simply follow me on the fediverse, <a href="../me">here’s where you can find me</a>.</p>
|
||||
</article>
|
||||
|
7
content/about/privacy/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
layout: layouts/base_full_width_text.njk
|
||||
---
|
||||
|
||||
# Privacy
|
||||
|
||||
I don’t collect any of your personal information, full-stop. All webfonts, icons, and images are hosted locally (these things can sometimes be used to [track people across the internet](https://www.firstpost.com/world/how-google-uses-fonts-to-track-what-users-do-online-and-sell-data-to-advertisers-12496552.html) otherwise). I use [umami](https://umami.is), an open source, privacy-respecting analytics tool, to see how many people visit this website.
|
@@ -7,7 +7,14 @@ eleventyNavigation:
|
||||
<h1>Nathan’s Blog.</h1>
|
||||
|
||||
<p class="page-block nodropcap">
|
||||
Looking for something in particular? Have a look at <a href="/tags/">this convenient list of post categories</a> to filter results by topic.
|
||||
Thank you for visiting my blog; I write about lots of things here, from <a href="/tags/storytime">personal stories</a>, to <a href="/tags/gnu-linux">tech</a>, <a href="/tags/vegan-cooking">food</a>, and <a href="/tags/incense">incense</a>. Explore all posts below or <a href="/tags/">choose a topic</a>. Want to know what I've been reading? <a href="../blogroll/">Exlore the blogroll</a>.<br />
|
||||
|
||||
<a href="/tags/">
|
||||
<button type="button">Topics »</button>
|
||||
</a>
|
||||
<a href="../blogroll/">
|
||||
<button type="button">Blogroll »</button>
|
||||
</a>
|
||||
</p>
|
||||
<h2>What’s New:</h2>
|
||||
{% set postslist = collections.posts %}
|
||||
|
@@ -10,5 +10,4 @@ imageAlt: An ASCII cow with a thought bubble containing the word wut
|
||||
mastodon_id: "111688829907363670"
|
||||
---
|
||||
As a big-old nerd, I spend a lot of time in the terminal on my computer. When you spend a lot of time somewhere, you want it to be comfortable. As a part of making my terminal more homey, I've set it up to give me a random quote each time I start a new session, delivered, of course, by a cow. Here's today's cowsay of the day:
|
||||
|
||||
{{ cowList.onScience | cowsay | safe }}
|
||||
|
32
content/blog/obligatory-site-updates-post.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Obligatory Site Updates Post
|
||||
description: All the new stuff I've done on this website lately.
|
||||
date: 2024-09-29
|
||||
tags:
|
||||
- Site Updates
|
||||
synopsis: All the new stuff I've done on this website lately.
|
||||
mastodon_id: "113222650648457852"
|
||||
---
|
||||
Here are a few new (and not-so-new, but good to know) features I've built for my humble website:
|
||||
|
||||
## A Sitemap for Humans
|
||||
I now have a (human readable) [sitemap](/sitemap), linked in the footer of each page, for easier discovery of the pages that aren't listed in the menu at the top, such as [colophon](/about/colophon), and [privacy](/about/privacy) pages, which are now separate from the [about page](/about).
|
||||
|
||||
I haven't automated this yet, mainly because I'm not sure how to best go about it; if any [Eleventy](https://www.11ty.dev/) enthusiasts out there have any suggestions, please let me know by commenting below using Mastodon!
|
||||
|
||||
## New Buttons
|
||||
Some pages now have buttons beneath their spiel that link to relevant pages that a reader may find useful. For instance, [colophon](/about/colophon), and [privacy](/about/privacy), and [contact](/me) pages, are linked from the [about page](/about); [/blog](/blog) now links to [tags](/tags), and…
|
||||
|
||||
## My Blogroll
|
||||
If you've been on the internet for a while (and I mean a *while*), you may remember the humble [blogroll](/blogroll): a list of blogs followed by the author of the blog you're reading, provided both as a benefit to readers and to help share traffic with other people who write interesting stuff.
|
||||
|
||||
As I am close to entirely removed from corporate social media, I get my news predominantly from my [newsreader](/about-feeds), which I very much enjoy going through each morning, often with a warm cup of tea. My [blogroll](/blogroll) contains most of the feeds I subscribe to, and it even provides a [convenient and very neatly formatted .opml file](/blogroll/nathanUpchurchBlogroll.opml), which you can (in theory) use to subscribe to my entire blogroll at once by importing it into your feed reader. (I very much hope it works as I haven't actually tested it, but do let me know if you try it.)
|
||||
|
||||
The [blogroll](/blogroll) links to both the main website and the feed for every entry, and contains a short description for each. Please bear in mind that I have been adding these as I discover them, so if it turns out I've listed the blog of someone who says mean things to kittens or something, please tell me so that I can remove their entry.
|
||||
|
||||
The [blogroll](/blogroll) and [.opml](/blogroll/nathanUpchurchBlogroll.opml) *are* automated, because there are an awful lot of feeds there and I have no interest in writing all that markup myself. If you'd like to know how that's done, you can [check out the repo](https://upchur.ch/gitea/n_u/nathanupchurch.com).
|
||||
|
||||
## A Feed for Everyone
|
||||
I write about all sorts of things, and I fully recognize that people who come here for posts such as [*The Secrets of Scrumptious Seitan*](/blog/the-secrets-of-scrumptious-seitan/) may not be especially interested in posts like [*How to Transfer Files Securely with the “scp” Command*](/blog/scp-command/), so I configured individual feeds for each tag.
|
||||
|
||||
What this means is if you go to the [blog](/blog) page, click on "Topics" to reach the [tags](/tags) page, and click on a tag, you'll find an RSS icon next to the title linked to a feed that only contains posts marked with that tag. Convenient, right?
|
41
content/blog/silvertip.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: "Silver Tip: an Incense Build Featuring Osmanthus and Mastic"
|
||||
description: "I make a fresh, sweet, and green incense build reminiscent of the flavor of white tea"
|
||||
date: 2024-09-20
|
||||
tags:
|
||||
- Incense
|
||||
synopsis: "I make a fresh, sweet, and green incense build reminiscent of the flavor of white tea."
|
||||
imageURL: /img/testAsh.webp
|
||||
imageAlt: "A small tin labelled 'test ash' beside a small glass jar containing matches."
|
||||
mastodon_id: "113173725532729481"
|
||||
---
|
||||
If my memory serves me, some time ago I tried a stick from [Yi-Xin](https://craft-incense.com/) that contained osmanthus flowers and mastic gum. I recall enjoying the combination, so when I found a bag of dried osmanthus on sale while [doing some online grocery shopping](https://www.sayweee.com), I set out to make something using these ingredients.
|
||||
|
||||
Having read that osmanthus, like lavender, was one of those few flowers that could be used successfully in incense, I was brimming with confidence as I ground them finely and made an attempt at a batch of sticks containing 19% of the powder. The result was ghastly. At this percentage, alongside that characteristic beautiful fruity fragrance was a proportionate helping of the acrid scent of burning plant matter. Following this failure, I put aside my hubris, opened my tin of 'test ash'[^1] and began testing incense powders comprised of differing ratios of osmanthus and base-wood in a series of trail-burning tests, eventually finding that a ratio of 10% osmanthus to base wood seemed to return a reasonably good fragrance in the burn.
|
||||
|
||||
[](/img/testAsh.webp)
|
||||
|
||||
Armed with this knowledge, I put together a build. The star aromatics sit atop a woody base of sandalwood and juniper sweetened by a touch of benzoin; the composition is slightly lifted with a minuscule amount of camphor, bound with guar gum and a little acacia gum. While also acting as a weak binder, the acacia gum is present to lower the burn temperature and strengthen the sticks.
|
||||
|
||||
## The Build
|
||||
|Ingredient|Grams|% of Build|
|
||||
|----------|------|-----------|
|
||||
|Juniperus Virginiana|2.6|35.62%|
|
||||
|Santalum Spicatum|2.6|35.62%|
|
||||
|Osmanthus Fragrans|0.73|10%|
|
||||
|Mastic Gum|0.5|6.85%|
|
||||
|Acacia Gum|0.3|4.11%|
|
||||
|Benzoin Siam|0.25|3.42%|
|
||||
|Guar Gum|0.25|3.42%|
|
||||
|Borneol Camphor|0.07|0.96%|
|
||||
|
||||
As with all of my incense, I extruded the dough into 2-2.5mm coreless sticks which I then dried on a mesh screen at room temperature and left to cure for a number of weeks.
|
||||
|
||||
## Conclusion
|
||||
The sticks this build produces offer a [quiet listen](https://kikohincense.com/pages/listening-to-incense), but I find it very pleasant. Something about the combination of juniper, mastic, and osmanthus forms a fragrance that's at once green and fruity, with a bright, peachy, stone-fruit note, all atop a woody base. After a couple of months, the camphor is barely there on the stick; whether it is present in the burn is difficult to say without trying a build sans borneol.[^2]
|
||||
|
||||
My partner has a small wood-burning backpacking stove they like to use to make tea while camping. While I haven't yet had the pleasure, I have to imagine that making a cup of white tea on such a stove in a juniper forest would smell similar to the fragrance of this stick.
|
||||
|
||||
|
||||
[^1]: I use the stick of a cotton swab to create a divot in the ash bed, which I carefully fill with incense powder to be tamped down, lit, and evaluated. When I'm done, I simply close the lid, shake the container, and drop it once or twice on a flat surface to smooth the ash and prepare it for the next use.
|
||||
[^2]: Such a tricky ingredient, camphor. The tiniest amount can seem utterly overwhelming when blending or on a fresh stick, and as incense cures and ages, it seems as though it may or may not mellow out in the burn.
|
24
content/blog/tech-wizard.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "The Office Tech Wizard"
|
||||
description: "Knowing how to operate a PDF viewer does not a tech wizard make; what it means to be good at your job."
|
||||
date: 2024-09-21
|
||||
tags:
|
||||
- Quick Thoughts
|
||||
- Rants
|
||||
synopsis: "Knowing how to operate a PDF viewer does not a tech wizard make; what it means to be good at your job."
|
||||
mastodon_id: "113178005978869507"
|
||||
---
|
||||
|
||||
I came across [this submission to *Not Always Right*](https://notalwaysright.com/pdf-pretty-darn-futile-part-2/) today, and it got me thinking about some of the attitudes towards technology I've seen over the years. There is a contingent of people in many workplaces who believe they can do a perfectly good job without investing the time in learning about the tech they use each day; after all, their work gets done, doesn't it? We've all encountered this sort; the sort of person who's so far removed from a basic understanding of the tools they use each day that they'll brand you the office tech-wizard for knowing how to use the zoom function in a PDF viewer, copy and paste with the keyboard alone, or *(gasp!)* googling how to restart the print spooler when a job gets stuck. And sure, many of these folks do manage to get things done, but a problem arises when you consider *how.*
|
||||
|
||||
Early career folk don't have the luxury of being bad at their tools; it's sink or swim. So when older colleagues or those later in their career don't know how to use a particular piece of software, guess who has to pick up the slack? This isn't necessarily a problem in and of itself; there's nothing wrong with not knowing something and needing a bit of assistance, but this quickly becomes a problem when people decide that they are exempt from learning because of their age, position, workload, et cetera. At this stage, one individual's job becomes a team effort; because of someone's attitude towards technology, another person who also has their own tasks and responsibilities is *doing their job with them.*
|
||||
|
||||
In considering what it is to be good at one's job, let's leave outcomes off the table for a minute. If someone has to rely on a team to do their job, no matter the result, can they seriously claim to be good at it? Surely knowledge and experience are moot if someone cannot actually perform their work. What sort of value does this individual provide an organization when they systematically reduce the productivity of their more capable colleagues each day? Further, in what other industry can people get away with this attitude? It's unthinkable that there might be a mechanic who refused to learn to work a hammer, a writer who refuses to sharpen a pencil, or a microbiologist who can't operate a microscope and is just 'too swamped' to learn how to prepare a slide. To me, a white-collar worker not knowing how to use the zoom function in a PDF viewer is equally ridiculous when working with PDFs is something they do on a regular basis.
|
||||
|
||||
So when we consider whether we are good at what we do, atop knowledge, experience, and outcomes, let's include a few new criteria:
|
||||
|
||||
1. Do we create or reduce work for others?
|
||||
2. Do we truly understand the tools that we use every day?
|
||||
3. Can we perform basic maintenance and troubleshooting on our tools?
|
||||
|
||||
…or do we rely on a wizard?
|
31
content/blog/that-time-i-drew-my-ex.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: That Time I Drew My Ex
|
||||
description: The tale of the time I made my best effort to draw my live-modeling ex. Also some not-very-good art.
|
||||
date: 2024-08-20
|
||||
tags:
|
||||
- Storytime
|
||||
- Quick Thoughts
|
||||
synopsis: The tale of the time I made my best effort to draw my live-modeling ex. Also some not-very-good art.
|
||||
imageURL: /img/doodle.webp
|
||||
imageAlt: A wiggly vector ice cream cone with a wee smiling face and colorful sprinkles. The cone is holding two smaller ice cream cones in its long, wiggly arms, one of which is wrapped around its body.
|
||||
mastodon_id: "112996800811207774"
|
||||
---
|
||||
At the start of the pandemic, I had just begun a relationship with an artist who had the occasional gig doing a bit of nude live modeling.
|
||||
|
||||
[](/img/doodle.webp)
|
||||
|
||||
When he invited me to join a session via zoom, I was apprehensive. Drawing has never been my strong suit. I can *doodle,* but I can't *draw.* But hey, I thought, I'm not completely devoid of artistic skill. I *have* been doing design work for years; while graphic design is not art, it's at least art-adjacent. Hell, when I sit down and take my time, I can produce something that's downright fridge-worthy!
|
||||
|
||||
[](/img/pastel.webp)
|
||||
|
||||
Prepared to do my best, I settled down with my laptop, some pencils, and a pad of paper. What I was not prepared for, however, was how quickly the poses would change. There I was, expecting a good chunk of time to carefully render my new boyfriend in loving detail, only to have the pose end before I'd even managed an outline! And so I changed my strategy: I decided to prioritize *speed.* That didn't work either. Here are some of the results:
|
||||
|
||||
[](/img/quicklydrawncat.webp)
|
||||
|
||||
[](/img/chicken.webp)
|
||||
|
||||
After much scribbling, I did begin to improve, eventually turning out this:
|
||||
|
||||
[](/img/notbad.webp)
|
||||
|
||||
I put the pencil down after that.
|
Before Width: | Height: | Size: 277 KiB |
Before Width: | Height: | Size: 462 KiB |
Before Width: | Height: | Size: 235 KiB |
22
content/blogroll/blogroll.njk
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
permalink: /blogroll/nathanUpchurchBlogroll.opml
|
||||
---
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<opml version="2.0">
|
||||
<head>
|
||||
<title>nathanUpchurchBlogroll.opml</title>
|
||||
<ownerName>Nathan Upchurch</ownerName>
|
||||
</head>
|
||||
<body>{% for category in blogroll.categories %}
|
||||
<outline id="{{ category.name }}" text="{{ category.name }}">{% for blog in category.blogs %}
|
||||
<outline
|
||||
text="{{ blog.title }}"
|
||||
description="{{ blog.description }}"
|
||||
htmlUrl="{{ blog.url }}"
|
||||
title="{{ blog.title }}"
|
||||
type="rss"
|
||||
version="RSS2"
|
||||
xmlUrl="{{ blog.feedUrl }}"/>{% endfor %}
|
||||
</outline>{% endfor %}
|
||||
</body>
|
||||
</opml>
|
27
content/blogroll/index.njk
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
layout: layouts/base.njk
|
||||
---
|
||||
<h1>Blogroll</h1>
|
||||
<p class="nodropcap page-block">Here are some of the blogs I subscribe to. You can click the RSS icon next to each to subscribe using <a href="../about-feeds/">your newsreader</a>, or import all of them at once by downloading and importing this convenient <a href="./nathanUpchurchBlogroll.opml" download>.opml file</a>.</p>
|
||||
{% for category in blogroll.categories %}
|
||||
<section class="blogroll">
|
||||
<h2>{{ category.name }}:</h2>
|
||||
{% for blog in category.blogs %}
|
||||
<div class="blogroll-category-group">
|
||||
<a href="{{ blog.url }}"><h3>{{ blog.title }}</h3></a>
|
||||
|
||||
<a href="{{ blog.feedUrl }}">
|
||||
<svg class="tag-feed-icon small" viewBox="0 0 155 155" width="153.349" height="152.909" version="1.0" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>RSS feed for {{ blog.url }}</title>
|
||||
<g transform="translate(-427.323 -373.814)">
|
||||
<ellipse style="opacity: 1; fill-opacity: 1; fill-rule: nonzero" transform="matrix(.86996 0 0 .86996 135.156 330.529)" cx="360.357" cy="200.643" rx="24.643" ry="23.929"></ellipse>
|
||||
<path style="fill-opacity: 1; fill-rule: evenodd" d="m427.835 455.057-.073-30.273c64.706 3.375 100.619 49.673 101.5 101.94h-30.318c-.503-45.942-31.74-69.996-71.11-71.667z"></path>
|
||||
<path style="fill-opacity: 1; fill-rule: evenodd" d="m428.201 404.571-.878-30.757C526.75 378.43 580 450.582 580.67 526.724l-31.197-.44c1.365-48.704-34.665-120.267-121.273-121.713Z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<p>{{ blog.description }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endfor %}
|
@@ -14,9 +14,9 @@ numberOfNowPostsToShow: 1
|
||||
{% set postslistCounter = postsCount %}
|
||||
{% set showPostListHeader = false %}
|
||||
{% include "postslist.njk" %}
|
||||
<a class="link-button" href="/now/">
|
||||
<a href="/now/">
|
||||
<button type="button">
|
||||
See more on the “now” page
|
||||
See more on the “now” page »
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
@@ -30,9 +30,9 @@ numberOfNowPostsToShow: 1
|
||||
|
||||
{% set morePosts = postsCount - numberOfLatestPostsToShow %}
|
||||
{% if morePosts > 0 %}
|
||||
<a class="link-button" href="/blog/">
|
||||
<a href="/blog/">
|
||||
<button type="button">
|
||||
See {{ morePosts }} more post{% if morePosts != 1 %}s{% endif %} in the blog
|
||||
See {{ morePosts }} more post{% if morePosts != 1 %}s{% endif %} in the blog »
|
||||
</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
28
content/now/now_2024-10-06.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Moving is Hard, Porches are the Best
|
||||
description: Moving, sitting on the porch, washing dishes like my forebears, and caving to peer pressure.
|
||||
synopsis: Moving, sitting on the porch, washing dishes like my forebears, and caving to peer pressure.
|
||||
date: 2024-10-06
|
||||
imageURL: /img/soap.webp
|
||||
imageAlt: A close-up of a packaged block of soap, reading: Marseille Soap, to cut, with olive oil.
|
||||
---
|
||||
About a month ago I moved just up the street, so to speak. The last time I moved, I had the cash to hire movers, but this September it was down to me and whatever poor saps I could cajole into helping in exchange for a warm fuzzy feeling. I will remain eternally grateful for my good friend and business partner Davey's help in making numerous van runs, as well as driving the U-Haul and schlepping numerous awkward and heavy containers and objects up a very tight flight of stairs, and I owe endless thanks to my partner Sol for helping me get everything arranged and organized. Oh, and in addition to being a first-rate moving helper, Davey also has a new album out; if you're in the market for a new punk record with album artwork designed by yours truly, you can [grab a copy here](https://daveydynamite.bandcamp.com/album/in-memory).
|
||||
|
||||
## What's this new place like, then?
|
||||
I've realized that for the past few years, my lifestyle has been neck and neck with my means. Lord knows it's [hard enough for the average American tax-payer to put anything by for a rainy day](https://www.gobankingrates.com/banking/banks/how-much-money-do-americans-have-in-their-bank-accounts-in-2024/), but the ability to pay off debt and save money is of particular importance to me as my partner and I are desperate to move back to my home-country of Scotland, which has made it nigh-on impossible for anyone but the wealthy to bring a non-citizen spouse into the country due to UK immigration policy falling victim to the spittle-flecked anti-immigrant ravings of certain English politicians. All this to say, the new place is a bit of a downgrade.
|
||||
|
||||
The story of *why* this place is so affordable is more than I care to inflict on the public at large, but suffice it to say that I recently ordered one of those little scraper handles with a bundle of bright orange plastic razor-blades. Cleanup aside, I'm having to make some adjustments. In the U.S., people tend to look at you with horror when you tell them that you don't have a shower at home, but I've been rather enjoying the cast iron claw-foot tub that sits a few feet beneath the slope of the roof. Pouring a pitcher of water over my head to rinse off makes me feel like I'm in an ancient Greek bath-house.
|
||||
|
||||
Some kind souls close to me have lent me a couple of AC units to help me contend with the lack of central air, and I just bought a larger Black and Decker window unit with a remote control for the bedroom. Going without a dishwasher is the difference making the most impact on my day to day life at the moment, as I tend to cook a lot, but I'm finding that there's something meditative about washing dishes by hand like my forebears. I've even procured a nice big block of Marseille Soap for the dishes — a one-kilogram block, green as the olive oil that it's made from, that comes with a little wire to help you cut off slices of the block to use in different places around the house.
|
||||
|
||||
[](/img/soap.webp)
|
||||
|
||||
## So I'm a porch person now.
|
||||
Besides the 33% reduction in rent, there are some distinct benefits to living where I now do. For a start, the downstairs neighbors are great people. My new street is much quieter owing to the lessened vehicle traffic, and it's a pretty street with lots of trees and some truly beautiful gardening work in places.
|
||||
|
||||
Living on a street where the outdoors is somewhere you want to be is, needless to say, a big improvement in terms of quality of life. It's a short walk to the river, which is a lovely place to eat lunch, and I do like to ensure that the local ducks eat their fill of frozen peas. Speaking of lunch, there's a cafe with at least one satisfying vegan option only a couple of doors down, and finally, there's a nice big porch at the front of the building, complete with ample furniture for sitting and observing the neighborhood. Dear reader, a month-in and I am already a fixture of the neighborhood alongside so many garden-gnomes and plastic flamingos. The porch is the perfect place to eat any meal, a great place to get to know your neighbors, and an easy way to spend plenty of time outdoors; the porch is where I want to be.
|
||||
|
||||
The apartment itself is not without its charms. There's a nice big room at the front that makes for a very comfortable study, with lots of space for working, playing my (muted) trombone, my bookcases and collection of aromatics, and even a solid wood high-top table that is now dedicated to incense-making. I have a large electric standing corner-desk that I raise and put my treadmill beneath to allow me to get some light exercise while I perform my day job; it was a trial fitting this all into the small room I had prior to the move. With everything in place the space feels cozy and well-appointed despite the features it lacks. All considered, I'm happy with the decision to move, even before reaping the benefits of a reduced monthly rent.
|
||||
|
||||
## Peer pressure
|
||||
I finally caved to the fear of missing out and joined Instagram solely to participate in an incense makers' group where some friends from the incense community hang out and talk incense-making technicalities. A staunch anti-corporate-social-media fediverse user, I resent joining a platform that scrapes user content for AI training, let alone the flagrant data collection and privacy violations, but, hell, I figure I'll make an exception just this once and *only* use it for the group.
|
23
content/sitemap/index.njk
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
layout: layouts/base_full_width_text.njk
|
||||
---
|
||||
|
||||
<section class="sitemap">
|
||||
<h1>Sitemap</h1>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li>
|
||||
<a href="/about">About</a>
|
||||
<ul>
|
||||
<li><a href="/about/colophon">Colophon</a></li>
|
||||
<li><a href="/me">Contact</a></li>
|
||||
<li><a href="/feed/feed.xml">Feed</a></li>
|
||||
<li><a href="/about/privacy">Privacy</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="/blog">Blog</a></li>
|
||||
<li><a href="/blogroll">Blogroll</a></li>
|
||||
<li><a href="/now">Now</a></li>
|
||||
<li><a href="/tags">Tags</a></li>
|
||||
</ul>
|
||||
</section>
|
@@ -11,8 +11,9 @@ pagination:
|
||||
addAllPagesToCollections: true
|
||||
layout: layouts/base.njk
|
||||
eleventyComputed:
|
||||
title: Tagged “{{ tag }}”
|
||||
title: Posts tagged “{{ tag }}”
|
||||
permalink: "/tags/{{ tag | slugify }}/"
|
||||
description: A list of every post I've written tagged “{{ tag }}.”
|
||||
---
|
||||
<h1>More posts tagged “{{ tag }}.”
|
||||
<a href="/feeds/{{ tag | slugify }}.xml">
|
||||
@@ -37,7 +38,7 @@ permalink: "/tags/{{ tag | slugify }}/"
|
||||
</svg>
|
||||
</a>
|
||||
</h1>
|
||||
<p class="page-block nodropcap">Here’s everything I’ve posted with the tag “{{ tag }}:”</p>
|
||||
<p class="page-block nodropcap">Here’s everything I’ve posted tagged “{{ tag }}.” Want to be notified when I post on this topic? <a href="/feeds/{{ tag | slugify }}.xml">Subscribe to “{{ tag }}.”</a></p>
|
||||
|
||||
{% set postslist = collections[ tag ] %}
|
||||
{% include "postslist.njk" %}
|
||||
|
@@ -1,34 +1,44 @@
|
||||
import { DateTime } from "luxon";
|
||||
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
|
||||
import markdownIt from "markdown-it";
|
||||
import markdownItFootnote from "markdown-it-footnote";
|
||||
import markdownItAnchor from "markdown-it-anchor";
|
||||
import mdfigcaption from 'markdown-it-image-figures';
|
||||
import mdfigcaption from "markdown-it-image-figures";
|
||||
import pluginRss from "@11ty/eleventy-plugin-rss";
|
||||
import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
||||
import pluginBundle from "@11ty/eleventy-plugin-bundle";
|
||||
import pluginNavigation from "@11ty/eleventy-navigation";
|
||||
import prettier from "prettier";
|
||||
import { EleventyHtmlBasePlugin } from "@11ty/eleventy";
|
||||
import {dateSuffixAdder, monthMap, timeFormatter} from "./public/js/modules/mastodonDateTools.js";
|
||||
import {
|
||||
dateSuffixAdder,
|
||||
monthMap,
|
||||
timeFormatter,
|
||||
} from "./public/js/modules/mastodonDateTools.js";
|
||||
|
||||
const figoptions = {
|
||||
figcaption: true
|
||||
figcaption: true,
|
||||
};
|
||||
|
||||
export default async function (eleventyConfig) {
|
||||
|
||||
// Helper Functions
|
||||
const multiReplace = (text, replacementTable) => {
|
||||
let newText = text;
|
||||
replacementTable.forEach(x => { newText = newText.replace(x[0], x[1]) });
|
||||
replacementTable.forEach((x) => {
|
||||
newText = newText.replace(x[0], x[1]);
|
||||
});
|
||||
return newText;
|
||||
};
|
||||
|
||||
// Transforms
|
||||
eleventyConfig.addTransform("prettier", function (content, outputPath) {
|
||||
if (outputPath && outputPath.endsWith(".html")) {
|
||||
return prettier.format(content, {parser: "html", bracketSameLine: true, vueIndentScriptAndStyle: true, singleAttributePerLine: true, htmlWhitespaceSensitivity: "ignore"});
|
||||
return prettier.format(content, {
|
||||
parser: "html",
|
||||
bracketSameLine: true,
|
||||
vueIndentScriptAndStyle: true,
|
||||
singleAttributePerLine: true,
|
||||
htmlWhitespaceSensitivity: "css",
|
||||
});
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
@@ -37,20 +47,9 @@ export default async function(eleventyConfig) {
|
||||
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
|
||||
|
||||
// Official plugins
|
||||
/*
|
||||
eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
|
||||
extensions: "html",
|
||||
formats: ["webp"],
|
||||
widths: [270,540,810,1080],
|
||||
defaultAttributes: {
|
||||
loading: "lazy",
|
||||
decoding: "async",
|
||||
},
|
||||
urlPath: "/img/",
|
||||
});*/
|
||||
eleventyConfig.addPlugin(pluginRss);
|
||||
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
|
||||
preAttributes: { tabindex: 0 }
|
||||
preAttributes: { tabindex: 0 },
|
||||
});
|
||||
eleventyConfig.addPlugin(pluginNavigation);
|
||||
eleventyConfig.addPlugin(EleventyHtmlBasePlugin);
|
||||
@@ -59,37 +58,42 @@ export default async function(eleventyConfig) {
|
||||
// Filters
|
||||
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
|
||||
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
||||
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
|
||||
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(
|
||||
format || "dd LLLL yyyy",
|
||||
);
|
||||
});
|
||||
|
||||
eleventyConfig.addFilter('htmlDateString', (dateObj) => {
|
||||
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
|
||||
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
||||
return DateTime.fromJSDate(dateObj, { zone: 'utc' }).toFormat('yyyy-LL-dd');
|
||||
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat("yyyy-LL-dd");
|
||||
});
|
||||
|
||||
eleventyConfig.addFilter("removeMostRecent", arr => {
|
||||
eleventyConfig.addFilter("removeMostRecent", (arr) => {
|
||||
return arr.slice(0, arr.length - 1);
|
||||
});
|
||||
|
||||
// Shortcodes
|
||||
|
||||
// Cowsay
|
||||
eleventyConfig.addNunjucksFilter("cowsay", cowText => {
|
||||
eleventyConfig.addFilter("cowsay", (cowText) => {
|
||||
const cowCaptionReplacementTable = [
|
||||
[`
|
||||
[
|
||||
`
|
||||
o ^__^
|
||||
o (oo)\\_______
|
||||
(__)\\ )\\/\\
|
||||
||----w |
|
||||
|| ||`, ''],
|
||||
[/\(\s+/g, ''],
|
||||
[/\s+\(/g, ''],
|
||||
[/_{3,}/g, ''],
|
||||
[/-{3,}/g, ''],
|
||||
[/\s\)/g, ''],
|
||||
[/\n/g, ''],
|
||||
[/\s{2,}/g, ' '],
|
||||
[/^ /, '']
|
||||
|| ||`,
|
||||
"",
|
||||
],
|
||||
[/\(\s+/g, ""],
|
||||
[/\s+\(/g, ""],
|
||||
[/_{3,}/g, ""],
|
||||
[/-{3,}/g, ""],
|
||||
[/\s\)/g, ""],
|
||||
[/\n/g, ""],
|
||||
[/\s{2,}/g, " "],
|
||||
[/^ /, ""],
|
||||
];
|
||||
|
||||
return `
|
||||
@@ -105,9 +109,7 @@ export default async function(eleventyConfig) {
|
||||
|
||||
// Embed a toot
|
||||
eleventyConfig.addAsyncShortcode("toot", async function (instance, ID) {
|
||||
const tootData = await fetch(
|
||||
`https://${instance}/api/v1/statuses/${ID}`
|
||||
);
|
||||
const tootData = await fetch(`https://${instance}/api/v1/statuses/${ID}`);
|
||||
|
||||
const toot = await tootData.json();
|
||||
|
||||
@@ -126,19 +128,29 @@ export default async function(eleventyConfig) {
|
||||
publish_date="${dateTime}"
|
||||
sharp_corner="">
|
||||
</wc-toot>
|
||||
`
|
||||
`;
|
||||
});
|
||||
|
||||
// Embed audio
|
||||
eleventyConfig.addShortcode(
|
||||
"audio",
|
||||
function (title, artist, media_url, cover_url) {
|
||||
return `
|
||||
<wc-card>
|
||||
<wc-mplayer
|
||||
title="${title}"
|
||||
artist="${artist}"
|
||||
media_url="${media_url}"
|
||||
cover_url="${cover_url}"
|
||||
/>
|
||||
</wc-card>
|
||||
`;
|
||||
},
|
||||
);
|
||||
|
||||
// Passthrough
|
||||
eleventyConfig.addPassthroughCopy({ 'public/xsl/*': "/xsl/" });
|
||||
eleventyConfig.addPassthroughCopy({ 'public/img/*': "/img/" });
|
||||
eleventyConfig.addPassthroughCopy({ 'public/robots.txt': "/" });
|
||||
eleventyConfig.addPassthroughCopy({ 'public/js/*': "/js/" });
|
||||
eleventyConfig.addPassthroughCopy({ 'public/js/webComponents/*': "/js/webComponents" });
|
||||
eleventyConfig.addPassthroughCopy({ 'public/js/modules/*': "/js/modules" });
|
||||
// Copying so that basic.xsl can use it
|
||||
eleventyConfig.addPassthroughCopy({ 'public/css/index.css': "/css/index.css" });
|
||||
eleventyConfig.addPassthroughCopy({ 'public/css/webfonts/*': "/css/webfonts/" });
|
||||
|
||||
eleventyConfig.addPassthroughCopy({ "./public/": "/" });
|
||||
|
||||
// Get the first `n` elements of a collection.
|
||||
eleventyConfig.addFilter("head", (array, n) => {
|
||||
@@ -158,37 +170,39 @@ export default async function(eleventyConfig) {
|
||||
});
|
||||
|
||||
// Return all the tags used in a collection
|
||||
eleventyConfig.addFilter("getAllTags", collection => {
|
||||
eleventyConfig.addFilter("getAllTags", (collection) => {
|
||||
let tagSet = new Set();
|
||||
for (let item of collection) {
|
||||
(item.data.tags || []).forEach(tag => tagSet.add(tag));
|
||||
(item.data.tags || []).forEach((tag) => tagSet.add(tag));
|
||||
}
|
||||
return Array.from(tagSet);
|
||||
});
|
||||
|
||||
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
|
||||
return (tags || []).filter(tag => ["all", "nav", "post", "posts"].indexOf(tag) === -1);
|
||||
return (tags || []).filter(
|
||||
(tag) => ["all", "nav", "post", "posts"].indexOf(tag) === -1,
|
||||
);
|
||||
});
|
||||
|
||||
// Customize Markdown library settings:
|
||||
let markdownItOptions = {
|
||||
html: true,
|
||||
typographer: true
|
||||
typographer: true,
|
||||
};
|
||||
|
||||
let mdLib = markdownIt(markdownItOptions);
|
||||
|
||||
eleventyConfig.amendLibrary("md", mdLib => {
|
||||
eleventyConfig.amendLibrary("md", (mdLib) => {
|
||||
mdLib
|
||||
.use(markdownItAnchor, {
|
||||
permalink: markdownItAnchor.permalink.ariaHidden({
|
||||
placement: "after",
|
||||
class: "header-anchor",
|
||||
symbol: "#",
|
||||
ariaHidden: false
|
||||
ariaHidden: false,
|
||||
}),
|
||||
level: [1, 2, 3, 4],
|
||||
slugify: eleventyConfig.getFilter("slugify")
|
||||
slugify: eleventyConfig.getFilter("slugify"),
|
||||
})
|
||||
.use(markdownItFootnote)
|
||||
.use(mdfigcaption, figoptions);
|
||||
@@ -197,12 +211,7 @@ export default async function(eleventyConfig) {
|
||||
eleventyConfig.setLibrary("md", mdLib);
|
||||
|
||||
return {
|
||||
templateFormats: [
|
||||
"md",
|
||||
"njk",
|
||||
"html",
|
||||
"liquid",
|
||||
],
|
||||
templateFormats: ["md", "njk", "html", "liquid"],
|
||||
|
||||
markdownTemplateEngine: "njk",
|
||||
|
||||
@@ -212,8 +221,8 @@ export default async function(eleventyConfig) {
|
||||
input: "content", // default: "."
|
||||
includes: "../_includes", // default: "_includes"
|
||||
data: "../_data", // default: "_data"
|
||||
output: "_site"
|
||||
output: "_site",
|
||||
},
|
||||
pathPrefix: "/",
|
||||
};
|
||||
};
|
||||
}
|
||||
|
24
netlify.toml
@@ -1,24 +0,0 @@
|
||||
[build]
|
||||
publish = "_site"
|
||||
command = "npm run build"
|
||||
|
||||
[[plugins]]
|
||||
|
||||
# Opt-in to the Netlify Lighthouse plugin (choose one):
|
||||
|
||||
# 1. Go to your site on https://app.netlify.com and navigate to the Integrations tab, search for the `Lighthouse` plugin
|
||||
# 2. Or via `npm install -D @netlify/plugin-lighthouse`
|
||||
|
||||
# Read more: https://github.com/netlify/netlify-plugin-lighthouse
|
||||
|
||||
package = "@netlify/plugin-lighthouse"
|
||||
|
||||
# optional, fails build when a category is below a threshold
|
||||
[plugins.inputs.thresholds]
|
||||
performance = 1.0
|
||||
accessibility = 1.0
|
||||
best-practices = 1.0
|
||||
seo = 1.0
|
||||
|
||||
[plugins.inputs]
|
||||
output_path = "reports/lighthouse/index.html"
|
@@ -9,7 +9,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Defaults */
|
||||
:root {
|
||||
--font-family: "Fraunces", serif;
|
||||
@@ -17,7 +16,10 @@
|
||||
--font-family-ui: "Manrope", sans-serif;
|
||||
--font-variation-default: "opsz" 18, "wght" 310, "SOFT" 40, "WONK" 0;
|
||||
--font-variation-ui: "wght" 500;
|
||||
--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;
|
||||
--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;
|
||||
--meta-font-family: "Fraunces", serif;
|
||||
--meta-font-size: var(--step--1);
|
||||
--meta-font-style: normal;
|
||||
@@ -42,7 +44,8 @@
|
||||
/* Design Tokens */
|
||||
:root {
|
||||
/* Animations */
|
||||
--slide-in-blurred-bottom: slide-in-blurred-bottom 0.75s cubic-bezier(0.230, 1.000, 0.320, 1.000) both;
|
||||
--slide-in-blurred-bottom: slide-in-blurred-bottom 0.75s
|
||||
cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
|
||||
/* Colors */
|
||||
--color-gray-20: #e0e0e0;
|
||||
@@ -50,7 +53,7 @@
|
||||
|
||||
--card-color: white;
|
||||
--contrast-color: #027860;
|
||||
--background-color: #FAF5F5;
|
||||
--background-color: #faf5f5;
|
||||
--rss-orange: rgb(255, 152, 0);
|
||||
--text-color: var(--color-gray-90);
|
||||
--text-color-link: var(--text-color);
|
||||
@@ -94,24 +97,29 @@
|
||||
--space-s-l: clamp(1.25rem, 0.2641rem + 4.9296vw, 3rem);
|
||||
|
||||
/* Fluid Grid Tokens - https://utopia.fyi/ */
|
||||
--grid-max-width: 55.50rem;
|
||||
--grid-max-width: 55.5rem;
|
||||
--grid-gutter: var(--space-s-s, clamp(1.25rem, 1.1092rem + 0.7042vw, 1.5rem));
|
||||
--grid-columns: 12;
|
||||
|
||||
/* Span grid utility */
|
||||
--span-grid: 1 / span 12;
|
||||
|
||||
/* Change <img> SVG color with filter */
|
||||
--logo-filter: brightness(0) saturate(100%) invert(16%) sepia(0%) saturate(1024%) hue-rotate(177deg) brightness(99%) contrast(88%);
|
||||
--logo-filter: brightness(0) saturate(100%) invert(16%) sepia(0%)
|
||||
saturate(1024%) hue-rotate(177deg) brightness(99%) contrast(88%);
|
||||
--icon-filter: none;
|
||||
|
||||
/* Corners */
|
||||
--border-radius: .3rem;
|
||||
--border-radius: 0.3rem;
|
||||
|
||||
/* Transitions */
|
||||
--transition-normal: all .3s;
|
||||
--transition-normal: all 0.3s;
|
||||
|
||||
/* Links */
|
||||
--link-decoration-thickness: .1rem;
|
||||
--link-decoration-thickness: 0.1rem;
|
||||
|
||||
/* Borders */
|
||||
--border-hr: 0.5px solid var(--color-gray-20);
|
||||
--border-nav: 1px solid var(--text-color);
|
||||
--border-nav-currentpage: var(--space-xs-s) solid var(--contrast-color);
|
||||
--border-nav-hover: var(--space-xs-s) solid var(--text-color);
|
||||
@@ -144,7 +152,8 @@
|
||||
|
||||
--background-color: #15202b;
|
||||
--logo-filter: none;
|
||||
--icon-filter: brightness(0) saturate(100%) invert(9%) sepia(76%) saturate(340%) hue-rotate(168deg) brightness(95%) contrast(94%);
|
||||
--icon-filter: brightness(0) saturate(100%) invert(9%) sepia(76%)
|
||||
saturate(340%) hue-rotate(168deg) brightness(95%) contrast(94%);
|
||||
}
|
||||
.socialLinks a li img {
|
||||
filter: auto;
|
||||
@@ -162,7 +171,7 @@ body {
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-family);
|
||||
font-variation-settings: var(--font-variation-default);
|
||||
font-variant-Ligatures: normal;
|
||||
font-variant-ligatures: normal;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -179,7 +188,12 @@ blockquote:before {
|
||||
margin-left: -4rem;
|
||||
margin-top: -2rem;
|
||||
position: fixed;
|
||||
filter: opacity(.15);
|
||||
filter: opacity(0.15);
|
||||
}
|
||||
.blogroll {
|
||||
h2:first-of-type {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
body {
|
||||
animation: var(--slide-in-blurred-bottom);
|
||||
@@ -190,7 +204,8 @@ body {
|
||||
padding-top: var(--space-m);
|
||||
padding-bottom: var(--space-m);
|
||||
}
|
||||
button, .nav-item {
|
||||
button,
|
||||
.nav-item {
|
||||
font-family: var(--font-family-ui);
|
||||
}
|
||||
code {
|
||||
@@ -204,7 +219,12 @@ code {
|
||||
background-color: var(--card-color);
|
||||
}
|
||||
}
|
||||
header, footer, main {
|
||||
.links-nextprev > .postlist-item-container {
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
header,
|
||||
footer,
|
||||
main {
|
||||
display: grid;
|
||||
gap: var(--grid-gutter);
|
||||
grid-template-columns: repeat(var(--grid-columns), 1fr);
|
||||
@@ -214,24 +234,38 @@ nav {
|
||||
}
|
||||
.now {
|
||||
display: grid;
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
padding-bottom: var(--space-xl);
|
||||
}
|
||||
section {
|
||||
display: grid;
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
&.full-width-text {
|
||||
p {
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
/* Add fleuron to last <p> in section */
|
||||
> p:not(blockquote > p):last-child:after {
|
||||
content: "\2766";
|
||||
display: inline;
|
||||
font-size: var(--step-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
::selection {
|
||||
background: var(--contrast-color);
|
||||
color: var(--background-color);
|
||||
}
|
||||
.page-block {
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
font-size: var(--step-1);
|
||||
margin: 0;
|
||||
padding-bottom: var(--space-xl);
|
||||
padding-top: var(--space-l);
|
||||
line-height: calc(var(--step-1) * 0.5 + var(--step-1));
|
||||
&:has(+ a > button) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
@@ -258,24 +292,34 @@ footer .webring {
|
||||
}
|
||||
footer p {
|
||||
font-size: var(--step-0);
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
h1, h2, h3 {
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
color: var(--text-color);
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
h1 {
|
||||
font-family: var(--font-family-headline);
|
||||
font-variation-settings: "opsz" 100, "wght" 500, "SOFT" 10, "WONK" 1;
|
||||
font-variation-settings:
|
||||
"opsz" 100,
|
||||
"wght" 500,
|
||||
"SOFT" 10,
|
||||
"WONK" 1;
|
||||
font-size: var(--step-5);
|
||||
font-style: normal;
|
||||
line-height: calc(var(--step-5) * 0.25 + var(--step-5));
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--step-2);
|
||||
font-variation-settings: "opsz" 50, "wght" 350, "SOFT" 20, "WONK" 1;
|
||||
font-variation-settings:
|
||||
"opsz" 50,
|
||||
"wght" 350,
|
||||
"SOFT" 20,
|
||||
"WONK" 1;
|
||||
padding-bottom: var(--space-l);
|
||||
padding-top: var(--space-xl);
|
||||
}
|
||||
@@ -292,7 +336,8 @@ main {
|
||||
grid-column: 1 / 12;
|
||||
padding-top: var(--space-3xl);
|
||||
}
|
||||
main > p > img, main > p > a > img {
|
||||
main > p > img,
|
||||
main > p > a > img {
|
||||
width: 100%;
|
||||
padding-top: var(--space-l);
|
||||
}
|
||||
@@ -301,17 +346,22 @@ main > p > img, main > p > a > img {
|
||||
padding-bottom: var(--space-s);
|
||||
}
|
||||
pre {
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
p, li {
|
||||
p,
|
||||
li {
|
||||
font-size: var(--step-0);
|
||||
line-height: calc(var(--step-0) * 0.5 + var(--step-0));
|
||||
}
|
||||
th {
|
||||
font-variation-settings: "opsz" 25, "wght" 500, "SOFT" 40, "WONK" 0;
|
||||
font-variation-settings:
|
||||
"opsz" 25,
|
||||
"wght" 500,
|
||||
"SOFT" 40,
|
||||
"WONK" 0;
|
||||
padding-bottom: var(--space-2xs);
|
||||
text-align: left;
|
||||
}
|
||||
@@ -328,7 +378,8 @@ figure > a > img {
|
||||
box-shadow: var(--space-2xs) var(--space-2xs) 0 0 var(--contrast-color);
|
||||
}
|
||||
|
||||
html.barebones, body.barebones {
|
||||
html.barebones,
|
||||
body.barebones {
|
||||
background-color: var(--background-color);
|
||||
text-align: center;
|
||||
}
|
||||
@@ -338,6 +389,9 @@ figcaption {
|
||||
font-style: italic;
|
||||
padding-top: var(--space-s);
|
||||
text-align: center;
|
||||
strong {
|
||||
font-variation-settings: "wght" 600;
|
||||
}
|
||||
}
|
||||
button {
|
||||
background-color: var(--contrast-color);
|
||||
@@ -351,19 +405,25 @@ button {
|
||||
padding: var(--space-2xs) var(--space-xs);
|
||||
text-transform: uppercase;
|
||||
transition: var(--transition-normal);
|
||||
white-space: nowrap;
|
||||
}
|
||||
button > img {
|
||||
max-width: 1em;
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
filter: var(--icon-filter);
|
||||
}
|
||||
a.link-button {
|
||||
align-items: start;
|
||||
display: flex;
|
||||
grid-column: 1 / span 12;
|
||||
text-align: center;
|
||||
a {
|
||||
button {
|
||||
margin-top: var(--space-m);
|
||||
}
|
||||
&:has(button) {
|
||||
text-decoration: none;
|
||||
}
|
||||
&:has(button.full-width) {
|
||||
display: inline-grid;
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
}
|
||||
button:hover {
|
||||
background-color: var(--color-gray-90);
|
||||
cursor: pointer;
|
||||
@@ -391,24 +451,72 @@ table th {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
/* Audio Player */
|
||||
wc-mplayer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
wc-mplayer::part(artist) {
|
||||
font-size: var(--meta-font-size);
|
||||
}
|
||||
|
||||
wc-mplayer::part(cover),
|
||||
wc-mplayer::part(coverContainer) {
|
||||
width: var(--space-3xl);
|
||||
height: var(--space-3xl);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
wc-mplayer::part(captionAndPlayer) {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
wc-mplayer::part(main) {
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
gap: var(--space-s);
|
||||
margin: 0;
|
||||
padding: var(--space-m);
|
||||
}
|
||||
|
||||
wc-mplayer::part(player) {
|
||||
align-self: flex-end;
|
||||
border-radius: var(--border-radius);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
wc-mplayer::part(title) {
|
||||
font-size: var(--step-1);
|
||||
font-variation-settings:
|
||||
"opsz" 50,
|
||||
"wght" 350,
|
||||
"SOFT" 20,
|
||||
"WONK" 1;
|
||||
}
|
||||
|
||||
/* Comments */
|
||||
#comments {
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
.continue-discussion {
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
}
|
||||
.continue-discussion button {
|
||||
margin-top: var(--space-xs);
|
||||
}
|
||||
wc-comment::part(author-link), wc-toot::part(author-link) {
|
||||
wc-comment::part(author-link),
|
||||
wc-toot::part(author-link) {
|
||||
font-size: var(--step-0);
|
||||
text-decoration: none;
|
||||
}
|
||||
wc-comment::part(main) {
|
||||
padding: var(--space-m);
|
||||
}
|
||||
wc-comment::part(publish-date), wc-toot::part(publish-date) {
|
||||
wc-comment::part(publish-date),
|
||||
wc-toot::part(publish-date) {
|
||||
font-family: var(--meta-font-family);
|
||||
font-size: var(--meta-font-size);
|
||||
font-style: var(--meta-font-style);
|
||||
@@ -419,7 +527,8 @@ wc-toot::part(main) {
|
||||
font-family: var(--meta-font-family);
|
||||
font-size: var(--step--1);
|
||||
}
|
||||
wc-toot::part(author), wc-toot::part(author-link){
|
||||
wc-toot::part(author),
|
||||
wc-toot::part(author-link) {
|
||||
color: white;
|
||||
font-style: var(--meta-font-style);
|
||||
font-variation-settings: "wght" 600;
|
||||
@@ -430,7 +539,7 @@ code {
|
||||
font-family: var(--font-family-monospace);
|
||||
}
|
||||
pre:not([class*="language-"]) {
|
||||
margin: .5em 0;
|
||||
margin: 0.5em 0;
|
||||
-moz-tab-size: var(--syntax-tab-size);
|
||||
-o-tab-size: var(--syntax-tab-size);
|
||||
tab-size: var(--syntax-tab-size);
|
||||
@@ -447,18 +556,47 @@ code {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* Dropcap */
|
||||
/* Footnotes */
|
||||
.footnotes-list {
|
||||
font-style: italic;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
> li,
|
||||
> li > p {
|
||||
font-size: var(--step--1);
|
||||
}
|
||||
}
|
||||
.footnote-item::marker {
|
||||
font-style: normal;
|
||||
}
|
||||
.footnote-ref {
|
||||
> a {
|
||||
font-size: var(--step--2);
|
||||
text-decoration: none;
|
||||
}
|
||||
:before {
|
||||
content: " ";
|
||||
}
|
||||
}
|
||||
hr.footnotes-sep {
|
||||
border: var(--border-hr);
|
||||
}
|
||||
|
||||
/* Dropcap */
|
||||
main > section > article > p:not(.nodropcap):first-of-type:first-letter {
|
||||
float: left;
|
||||
font-size: var(--step-6);
|
||||
padding: .5rem .5rem .5rem .5rem;
|
||||
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
|
||||
color: var(--contrast-color);
|
||||
border: solid 2px var(--contrast-color);
|
||||
font-family: var(--font-family-headline);
|
||||
font-variation-settings: "opsz" 144, "wght" 500, "SOFT" 10, "WONK" 0;
|
||||
margin: .5rem .7rem 0 0;
|
||||
border-radius: .2em;
|
||||
font-variation-settings:
|
||||
"opsz" 144,
|
||||
"wght" 500,
|
||||
"SOFT" 10,
|
||||
"WONK" 0;
|
||||
margin: 0.5rem 0.7rem 0 0;
|
||||
border-radius: 0.2em;
|
||||
border-top-left-radius: 0;
|
||||
}
|
||||
|
||||
@@ -487,18 +625,13 @@ nav ul {
|
||||
.nav-icon {
|
||||
fill: var(--color-gray-90);
|
||||
height: var(--space-2xs);
|
||||
margin-right: .25rem;
|
||||
margin-right: 0.25rem;
|
||||
transition: var(--transition-normal);
|
||||
width: var(--space-2xs);
|
||||
}
|
||||
.nav-item {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
border-top: var(--border-nav);
|
||||
}
|
||||
.nav-item li {
|
||||
align-items: baseline;
|
||||
color: var(--text-color);
|
||||
border-top: var(--border-nav);
|
||||
display: flex;
|
||||
font-size: var(--step--2);
|
||||
font-variation-settings: var(--font-variation-ui);
|
||||
@@ -509,37 +642,39 @@ nav ul {
|
||||
transition: var(--transition-normal);
|
||||
letter-spacing: var(--ui-letter-spacing);
|
||||
}
|
||||
.nav-item:hover {
|
||||
border-top: var(--border-nav-hover);
|
||||
.nav-item a {
|
||||
color: var(--text-color);
|
||||
margin-top: calc(var(--space-xs-s) * -1); /* Compensate for padding */
|
||||
padding-top: var(--space-xs-s); /* Give <a> a larger click area */
|
||||
}
|
||||
/* Compensate for increased border thickness on hover of a.nav-item */
|
||||
.nav-item:hover li {
|
||||
margin-top: calc(var(--space-xs-s) * -1);
|
||||
.nav-item:hover {
|
||||
border-top: var(--border-nav-hover); /* Increase border thickness */
|
||||
}
|
||||
.nav-item:hover a {
|
||||
margin-top: calc(
|
||||
var(--space-xs-s) * -2
|
||||
); /* Compensate for border thickness */
|
||||
}
|
||||
.nav-item a[href]:visited {
|
||||
color: var(--text-color);
|
||||
}
|
||||
.nav-item a[href]:hover {
|
||||
.nav-item:hover a[href] {
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
|
||||
}
|
||||
.nav-item a[href]:not(:hover) {
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
.nav-item[data-currentpage="true"] {
|
||||
border-top: var(--border-nav-currentpage);
|
||||
}
|
||||
.nav-item[data-currentpage="true"] a,
|
||||
.nav-item[data-currentpage="true"] a[href]:visited,
|
||||
.nav-item[data-currentpage="true"]:hover a {
|
||||
color: var(--contrast-color);
|
||||
}
|
||||
.nav-item[data-currentpage="true"] li {
|
||||
margin-top: calc(var(--space-xs-s) * -1);
|
||||
}
|
||||
.nav a[href][aria-current="page"] li {
|
||||
color: var(--contrast-color);
|
||||
}
|
||||
.subscribe:hover {
|
||||
color: var(--text-color);
|
||||
margin-top: calc(
|
||||
var(--space-xs-s) * -2
|
||||
); /* Compensate for border thickness */
|
||||
}
|
||||
|
||||
/* Posts list */
|
||||
@@ -560,17 +695,19 @@ nav ul {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.postlist, .links-nextprev {
|
||||
.postlist,
|
||||
.links-nextprev {
|
||||
container: postlist / inline-size;
|
||||
}
|
||||
|
||||
.post-image-container {
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--box-shadow);
|
||||
height: 15rem;
|
||||
margin-left: calc(var(--space-l) * -1);
|
||||
max-height: 15rem;
|
||||
overflow: hidden;
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
.postlist-date,
|
||||
@@ -583,7 +720,7 @@ nav ul {
|
||||
}
|
||||
.postlist-link {
|
||||
font-size: var(--step-5); /* 19px /16 */
|
||||
padding-right: .5em;
|
||||
padding-right: 0.5em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -653,9 +790,13 @@ a.post-tag:hover {
|
||||
}
|
||||
.tag-feed-icon {
|
||||
fill: var(--rss-orange);
|
||||
height: 3.5rem;
|
||||
height: var(--space-m);
|
||||
transition: var(--transition-normal);
|
||||
width: var(--space-l);
|
||||
width: var(--space-m);
|
||||
&.small {
|
||||
height: var(--space-s);
|
||||
width: var(--space-s);
|
||||
}
|
||||
}
|
||||
.taglist {
|
||||
display: flex;
|
||||
@@ -664,7 +805,7 @@ a.post-tag:hover {
|
||||
padding-left: 0;
|
||||
}
|
||||
.taglist li {
|
||||
margin: 0em .5em 1.25em 0em;
|
||||
margin: 0em 0.5em 1.25em 0em;
|
||||
}
|
||||
.taglist li a {
|
||||
font-size: var(--step-2);
|
||||
@@ -688,7 +829,11 @@ a.post-tag:hover {
|
||||
padding-left: var(--space-s);
|
||||
}
|
||||
|
||||
.post-metadata p, .post-metadata ul, .post-metadata ul li, time, .metadata {
|
||||
.post-metadata p,
|
||||
.post-metadata ul,
|
||||
.post-metadata ul li,
|
||||
time,
|
||||
.metadata {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
font-size: var(--meta-font-size);
|
||||
@@ -701,7 +846,7 @@ a.post-tag:hover {
|
||||
}
|
||||
|
||||
.post-metadata time {
|
||||
padding-left: .15rem;
|
||||
padding-left: 0.15rem;
|
||||
}
|
||||
|
||||
.profilePic:not(.links-container > img.profilePic) {
|
||||
@@ -712,7 +857,7 @@ a.post-tag:hover {
|
||||
/* Direct Links / Markdown Headers */
|
||||
a.header-anchor {
|
||||
font-style: normal;
|
||||
margin-left: .1em;
|
||||
margin-left: 0.1em;
|
||||
text-decoration: none;
|
||||
}
|
||||
a[href].header-anchor,
|
||||
@@ -733,16 +878,35 @@ h2 + .header-anchor {
|
||||
|
||||
/* Components */
|
||||
article.post {
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: var(--span-grid);
|
||||
container: article / inline-size;
|
||||
}
|
||||
|
||||
/* Adds fleuron to article end */
|
||||
article.post > p:not(blockquote > p):last-child:after {
|
||||
/* Add fleuron after last <p> in article */
|
||||
> p:not(blockquote > p):last-child:after {
|
||||
content: "\2766";
|
||||
display: inline;
|
||||
font-size: var(--step-1);
|
||||
}
|
||||
}
|
||||
.blogroll {
|
||||
display: inline;
|
||||
}
|
||||
.blogroll-category-group {
|
||||
margin-bottom: var(--space-l);
|
||||
margin-left: var(--space-m);
|
||||
h3 {
|
||||
display: inline;
|
||||
}
|
||||
p {
|
||||
margin: var(--space-2xs) auto;
|
||||
}
|
||||
}
|
||||
/* Add fleuron after <p> in article when footnotes are present */
|
||||
p:has(+ hr.footnotes-sep):after {
|
||||
content: "\2766";
|
||||
display: inline;
|
||||
font-size: var(--step-1);
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
.grid-container {
|
||||
max-width: var(--grid-max-width);
|
||||
|
@@ -2,7 +2,10 @@
|
||||
|
||||
.links-container {
|
||||
grid-column: 1 / span 12;
|
||||
padding: 0 var(--space-3xl);
|
||||
.socialLinks {
|
||||
max-width: calc(var(--space-3xl) * 3);
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.socialLinks a button {
|
||||
|
@@ -1,16 +1,19 @@
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: Manrope;
|
||||
font-style: normal;
|
||||
font-weight: 200 900;
|
||||
src: url(/css/webfonts/Manrope[wght].woff2) format("woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: Fraunces;
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
src: url(/css/webfonts/Fraunces[SOFT,WONK,opsz,wght].woff2) format("woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
font-family: Fraunces;
|
||||
font-style: italic;
|
||||
font-weight: 100 900;
|
||||
|
BIN
public/img/cedar_frank_copy.webp
Normal file
After Width: | Height: | Size: 154 KiB |
BIN
public/img/chicken.webp
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
public/img/doodle.webp
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
public/img/incense_seal_copy.webp
Normal file
After Width: | Height: | Size: 60 KiB |
56
public/img/logo_favicon.svg.2024_08_06_11_23_44.0.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="8.4666662mm"
|
||||
height="8.4666662mm"
|
||||
viewBox="0 0 8.4666662 8.4666662"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="logo_favicon.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="9.5624995"
|
||||
inkscape:cx="25.098041"
|
||||
inkscape:cy="34.19608"
|
||||
inkscape:current-layer="g1"
|
||||
inkscape:window-width="1337"
|
||||
inkscape:window-height="1077"
|
||||
inkscape:window-x="522"
|
||||
inkscape:window-y="231"
|
||||
inkscape:window-maximized="0" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-23.248082,-20.452073)">
|
||||
<g
|
||||
id="g1">
|
||||
<path
|
||||
d="m 24.299497,21.503489 v 1.520267 0.734109 2.589192 c 0,0.842244 0.678022,1.520267 1.520266,1.520267 h 3.323302 c 0.842243,0 1.520266,-0.678023 1.520266,-1.520267 v -3.323301 c 0,-0.842245 -0.678023,-1.520267 -1.520266,-1.520267 h -2.875068 -0.448234 z"
|
||||
style="fill:#faf5f5;fill-opacity:1;stroke-width:0.121929;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path3" />
|
||||
<path
|
||||
d="m 29.856464,26.04708 c 0.144453,0 0.263097,0.04267 0.356568,0.127641 0.09347,0.08497 0.140559,0.197242 0.140559,0.337447 0,0.140205 -0.04709,0.252992 -0.140559,0.337964 -0.09347,0.08497 -0.212115,0.127124 -0.356568,0.127124 -0.148702,0 -0.269815,-0.04215 -0.363285,-0.127124 -0.08922,-0.08497 -0.133842,-0.197759 -0.133842,-0.337964 0,-0.140205 0.04462,-0.252474 0.133842,-0.337447 0.09347,-0.08497 0.214583,-0.127641 0.363285,-0.127641 z"
|
||||
style="fill:#333333;stroke-width:0.162218;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path4" />
|
||||
<path
|
||||
d="m 24.764269,22.375987 v 0.12764 c 0.140203,0.0042 0.244145,0.02142 0.312125,0.05116 0.07223,0.02549 0.11932,0.07648 0.14056,0.152962 0.02549,0.07223 0.03824,0.186965 0.03824,0.344165 v 2.944007 c 0,0.186938 -0.01275,0.33355 -0.03824,0.439766 -0.02124,0.106217 -0.06833,0.182714 -0.14056,0.229443 -0.06798,0.04673 -0.171922,0.07861 -0.312125,0.0956 v 0.127641 c 0.06798,-0.0085 0.152798,-0.01292 0.254764,-0.01292 0.106216,-0.0042 0.210675,-0.0062 0.312643,-0.0062 0.114713,0 0.235827,0.002 0.363285,0.0062 0.127459,0 0.231396,0.0044 0.312126,0.01292 v -0.127641 c -0.178443,-0.01699 -0.312306,-0.04887 -0.401526,-0.0956 -0.08497,-0.05098 -0.140392,-0.131381 -0.165882,-0.241845 -0.02549,-0.114713 -0.03824,-0.274073 -0.03824,-0.478007 v -2.753321 l 2.7342,3.715536 c 0.05098,-0.0042 0.09755,-0.0062 0.140043,-0.0062 0.04673,0 0.0894,0.002 0.127641,0.0062 v -3.639054 c 0,-0.19119 0.01079,-0.3378 0.03204,-0.439767 0.02549,-0.106217 0.07401,-0.182713 0.146245,-0.229443 0.07223,-0.05098 0.176685,-0.08285 0.312642,-0.0956 v -0.12764 c -0.06373,0.0043 -0.149066,0.0087 -0.255282,0.01292 -0.101965,0.0042 -0.205909,0.0062 -0.312125,0.0062 -0.110465,0 -0.231578,-0.002 -0.363286,-0.0062 -0.127457,-0.0043 -0.231405,-0.0087 -0.312125,-0.01292 v 0.12764 c 0.182692,0.01274 0.316556,0.04461 0.401526,0.0956 0.08497,0.05098 0.139874,0.131898 0.165364,0.242362 0.02549,0.110465 0.03824,0.269823 0.03824,0.478007 v 2.236556 l -2.389518,-3.180167 c -0.07223,0.0043 -0.155094,0.0087 -0.248564,0.01292 -0.09347,0.0042 -0.189084,0.0062 -0.286804,0.0062 -0.101968,0 -0.206427,-0.002 -0.312643,-0.0062 -0.101966,-0.0043 -0.186785,-0.0087 -0.254764,-0.01292 z"
|
||||
style="fill:#333333;stroke-width:0.162218;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path5" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
BIN
public/img/notbad.webp
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
public/img/pastel.webp
Normal file
After Width: | Height: | Size: 464 KiB |
BIN
public/img/pexels-ds-stories-9228363_copy.webp
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
public/img/quicklydrawncat.webp
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
public/img/rms.jpg
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
public/img/scribus_copy.webp
Normal file
After Width: | Height: | Size: 232 KiB |
BIN
public/img/sidePanel/Scriptinator_copy.avif
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
public/img/sidePanel/getWidgets_copy.avif
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
public/img/sidePanel/panelSettings_copy.avif
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/img/sidePanel/printIDs_copy.avif
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/img/sidePanel/printIDs_copy.avif~
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/img/sidePanel/sidePanel_copy.avif
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
public/img/soap.webp
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
public/img/testAsh.webp
Normal file
After Width: | Height: | Size: 108 KiB |
@@ -1,4 +1,5 @@
|
||||
import './webComponents/card.js';
|
||||
import './webComponents/profilePic.js';
|
||||
import './webComponents/comment.js';
|
||||
import './webComponents/toot.js';
|
||||
import "./webComponents/card.js";
|
||||
import "./webComponents/profilePic.js";
|
||||
import "./webComponents/comment.js";
|
||||
import "./webComponents/toot.js";
|
||||
import "./webComponents/musicPlayer.js";
|
||||
|
51
public/js/webComponents/musicPlayer.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const template = document.createElement("template");
|
||||
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
.cover {
|
||||
object-fit: cover;
|
||||
}
|
||||
</style>
|
||||
|
||||
<figure class="mplayer" part="main">
|
||||
<div class="coverContainer" part="coverContainer">
|
||||
<img src="" class="cover" part="cover">
|
||||
</div>
|
||||
<div part="captionAndPlayer">
|
||||
<figcaption part="caption">
|
||||
<span class="title" part="title"></span><br /><span class="artist" part="artist"></span>
|
||||
</figcaption>
|
||||
<audio controls src="" class="player" part="player"></audio>
|
||||
</div>
|
||||
</figure>
|
||||
`;
|
||||
|
||||
class mplayer extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._shadowRoot = this.attachShadow({ mode: "open" });
|
||||
this._shadowRoot.appendChild(template.content.cloneNode(true));
|
||||
this.$mplayer = this._shadowRoot.querySelector(".mplayer");
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ["title", "artist", "media_url", "cover_url"];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldVal, newVal) {
|
||||
if (oldVal != newVal) {
|
||||
this[name] = newVal;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.$mplayer.querySelector(".title").innerHTML = this.title;
|
||||
this.$mplayer.querySelector(".artist").innerHTML = this.artist;
|
||||
this.$mplayer.querySelector(".player").src = this.media_url;
|
||||
this.$mplayer.querySelector(".coverContainer > img").src = this.cover_url;
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("wc-mplayer", mplayer);
|