Formatting and cleanup

This commit is contained in:
2024-11-11 21:36:33 +00:00
parent 232599a7f8
commit 8adccc6f95
30 changed files with 142 additions and 117 deletions

View File

@@ -1,3 +1,4 @@
{
"trailingComma": "none"
"trailingComma": "none",
"singleQuote": true
}

View File

@@ -1,45 +1,33 @@
import { DateTime } from "luxon";
import { DateTime } from 'luxon';
import markdownIt from 'markdown-it';
export default function (eleventyConfig) {
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
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'
);
});
// Get the first `n` elements of a collection.
eleventyConfig.addFilter("head", (array, n) => {
if (!Array.isArray(array) || array.length === 0) {
return [];
}
if (n < 0) {
return array.slice(n);
}
return array.slice(0, n);
});
// Return the smallest number argument
eleventyConfig.addFilter("min", (...numbers) => {
return Math.min.apply(null, numbers);
});
// Return the keys used in an object
eleventyConfig.addFilter("getKeys", (target) => {
eleventyConfig.addFilter('getKeys', (target) => {
return Object.keys(target);
});
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
eleventyConfig.addFilter('filterTagList', function filterTagList(tags) {
return (tags || []).filter(
(tag) => ["all", "posts"].indexOf(tag) === -1
(tag) => ['all', 'posts'].indexOf(tag) === -1
);
});
eleventyConfig.addFilter('md', function (content = '') {
return markdownIt({ html: true }).render(content);
});
}

View File

@@ -1,5 +1,5 @@
import { z } from "zod";
import { fromZodError } from "zod-validation-error";
import { z } from 'zod';
import { fromZodError } from 'zod-validation-error';
export default function (data) {
// Draft content, validate `draft` front matter

View File

@@ -1,11 +1,11 @@
export default {
title: "Chris Kaczor",
url: "https://chriskaczor.com/",
language: "en",
description: "Code, Critters, and whatever I feel like writing about.",
title: 'Chris Kaczor',
url: 'https://chriskaczor.com/',
language: 'en',
description: 'Code, Critters, and whatever I feel like writing about.',
author: {
name: "Chris Kaczor",
email: "chris@kaczor.us",
url: "https://chriskaczor.com/about/"
name: 'Chris Kaczor',
email: 'chris@kaczor.us',
url: 'https://chriskaczor.com/about/'
}
};

View File

@@ -7,12 +7,15 @@
<meta name="description" content="{{ description or metadata.description }}">
<link rel="alternate" href="feed/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png?v=2">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png?v=2">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png?v=2">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
{#- Uncomment this if youd like folks to know that you used Eleventy to build your site! #}
{#- <meta name="generator" content="{{ eleventy.generator }}"> #}
<meta name="generator" content="{{ eleventy.generator }}">
{#-
Plain-text bundles are provided via the `eleventy-plugin-bundle` plugin:
@@ -26,7 +29,7 @@
#}
{#- Add an arbitrary string to the bundle #}
{%- css %}/* This is an arbitrary CSS string added to the bundle */{% endcss %}
{# {%- css %}/* This is an arbitrary CSS string added to the bundle */{% endcss %} #}
{#- Add the contents of a file to the bundle #}
{%- css %}{% include "public/css/index.css" %}{% endcss %}
{#- Or you can add from node_modules #}
@@ -36,8 +39,6 @@
<style>
{% getBundle "css" %}
</style>
{#- Renders the CSS bundle using a separate file, if you can't set CSP directive style-src: 'unsafe-inline' #}
{#- <link rel="stylesheet" href="{% getBundleFileUrl "css" %}"> #}
{#- Add the heading-anchors web component to the JavaScript bundle #}
{%- js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
@@ -54,7 +55,9 @@
<ul class="nav">
{%- for entry in collections.all | eleventyNavigation %}
<li class="nav-item">
<a href="{{ entry.url }}"{% if entry.url == page.url %} aria-current="page"{% endif %}>{{ entry.title }}</a>
<a href="{{ entry.url }}"{% if entry.url == page.url %} aria-current="page"{% endif %}>
{{ entry.title }}
</a>
</li>
{%- endfor %}
</ul>
@@ -69,8 +72,7 @@
<footer>
<p>
<em>Built with <a href="https://www.11ty.dev/">{{ eleventy.generator }}</a>
</em>
Built with <a href="https://www.11ty.dev/">{{ eleventy.generator }}</a>
</p>
</footer>

View File

@@ -1,14 +1,30 @@
{%- css %}.postlist { counter-reset: start-from {{ (postslistCounter or postslist.length) + 1 }} }{% endcss %}
<ol reversed class="postlist">
<ul reversed class="postlist">
{% for post in postslist | reverse %}
<li class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ post.url }}" class="postlist-link">
{% if post.data.title %}{{ post.data.title }}
{% if post.data.title %}
{{ post.data.title }}
{% else %}
<code>{{ post.url }}</code>
{% endif %}
</a>
<time class="postlist-date" datetime="{{ post.date | htmlDateString }}">{{ post.date | readableDate("LLLL yyyy") }}</time>
<span class="postlist-byline">
<time class="postlist-date" datetime="{{ post.date | htmlDateString }}">{{ post.date | readableDate }}</time>
<ul class="postlist-tags">
{%- for tag in post.data.tags | filterTagList %}
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
<li>
<a href="{{ tagUrl }}" class="postlist-tag">{{ tag }}</a>
{%- if not loop.last %}, {% endif %}
</li>
{%- endfor %}
</ul>
</span>
{{ post.data.page.excerpt | md | safe }}
<a href="{{ post.url }}" class="postlist-read-more">
Read more
</a>
</li>
{% endfor %}
</ol>
</ul>

View File

@@ -2,6 +2,7 @@
permalink: 404.html
eleventyExcludeFromCollections: true
---
# Content not found.
Go <a href="index.njk">home</a>.

View File

@@ -4,6 +4,7 @@ const eleventyNavigation = {
order: 3
};
---
# About
I am a person that writes stuff.

View File

@@ -1,10 +0,0 @@
---js
const eleventyNavigation = {
key: "Archive",
order: 2
};
---
<h1>Archive</h1>
{% set postslist = collections.posts %}
{% include "postslist.njk" %}

View File

@@ -8,6 +8,8 @@ tags:
When I started this blog I had recently been laid off and figured it was as good a time as any to give some visibility to the code I had been creating over the years rather than hoarding it like a jealous dragon. I intended to keep up with it but then I started a new job and the writing sort of fell by the wayside. I kept working on projects when I could but never really got the chance to write about them. I'm hoping to be a bit more consistent this time around but only time will tell.
<!-- excerpt -->
I've been mostly working on completely recreating my home monitoring project with both new hardware and software - I'll write more about that in upcoming posts.
For the last week or so I've been doing [Advent of Code 2019](https://adventofcode.com/) so that I can follow along with my son. He got a good head start due to a few snow days at the beginning of the month but I've gotten ahead of him a bit as the challenges have gotten harder. We just spent some time getting his Intcode computer for day 9 working properly and I nearly swore off the entire contest while doing the second part of day 12 - the coding for that part wasn't really a problem but it took me a bit to figure out the concept for doing it without brute force. I think it would have been more fair if the challenge better explained how to solve the problem and left the coding up to the participant but that's probably just me being whiny. =) We've been posting our code in our GitHub repos in case anyone wants a peek:

View File

@@ -8,6 +8,8 @@ tags:
Now that I've written about my [FloatingStatusWindow](https://github.com/ckaczor/FloatingStatusWindow) library I can start to talk about the projects that use it. First up is the [ProcessCpuUsageStatusWindow](https://github.com/ckaczor/ProcessCpuUsageStatusWindow) project.
<!-- excerpt -->
[![](images/ProcessCpuUsageStatusWindow.png)](images/ProcessCpuUsageStatusWindow.png)
It is basically a mini task manager showing the top X processes by CPU usage and the total CPU usage of the system. The values update automatically every 2 seconds.

View File

@@ -7,6 +7,8 @@ tags:
My wife and a friend run The Crafty Coop (edit: now closed) - an event planning business that also sells handmade party decorations/favors online and at craft shows. One of the ways I help out is as the designated "IT guy" by handling the web/email hosting and other technical stuff.
<!-- excerpt -->
When we were initially setting up the website using WordPress we looked for a widget that would generate a listing of their Etsy shop items but we weren't really happy with the ones we found - they either required that the Etsy shop be broken up into sections or they didn't quite display the way we wanted. I decided to try to write my own instead of tweaking one of the existing ones and [Etsy Shop Widget](https://github.com/ckaczor/etsy-shop-widget) was born.
[![](images/etsy-shop-widget-widget.png)](images/etsy-shop-widget-widget.png)

View File

@@ -7,6 +7,8 @@ tags:
One of my most complete projects is [Feed Center](https://github.com/ckaczor/FeedCenter) - an RSS feed reader designed to blend in with the Windows desktop.
<!-- excerpt -->
[![](images/Feed-Center-300x188.png)](images/Feed-Center.png)
Years ago when push technology was the hot new thing I got my online news from applications like PointCast and MSNBC News Alert - but they were eventually discontinued as web sites moved to other delivery mechanisms like RSS feeds. I tried to find an RSS reader but never really found one that I liked. I didn't want some Outlook lookalike that I had to specifically open and read through. I wanted an app that would blend in with my desktop as much as possible and be something that I could glance at every so often for the latest news. At some point I started fiddling with creating my own and Feed Center is the result.

View File

@@ -8,6 +8,8 @@ tags:
Something that shows up in a lot of my projects is my [FloatingStatusWindow](https://github.com/ckaczor/FloatingStatusWindow) library. It allows the creation of something akin to a desktop widget that displays simple text and blends in with the Windows desktop. This is what several of them look like in the corner of my secondary monitor:
<!-- excerpt -->
[![](images/Windows-Locked.png)](images/Windows-Locked.png)
Each one is a separate project that uses the core library to create and manage the window. The code for a few of these is on [GitHub](https://github.com/ckaczor) and I'm working to add more.

View File

@@ -8,6 +8,8 @@ tags:
Being a programmer at heart it seems appropriate to stick with the classic "hello world" for starting off!
<!-- excerpt -->
I've been programming in one way or another since my dad bought a [TRS-80 Model I](https://en.wikipedia.org/wiki/TRS-80) many years ago. My first real project was a BASIC program that would convert text to pig Latin and it all took off from there. Now that I think about it there's even a chance that I still have that original code - I should go look for it!
Recently I was adding a new project to my Bitbucket account and realized I had a lot of code in there that might be useful for other people and it was a shame to keep it locked up. I had been hording it as if it was something secret but it really didn't need to be. I decided that I would made as much as possible public on GitHub and write a little bit about each project. Some of it is certainly a bit crusty but there's a chance some of it might be useful. I've only managed to move a little so far so expect more to show up as I make progress.

View File

@@ -7,6 +7,8 @@ tags:
The next project up is [LaundryMonitor](https://github.com/ckaczor/LaundryMonitor) which uses the most hardware of anything I've done so far.
<!-- excerpt -->
I'd always wanted something that would let us tell if the washing machine or dryer was running but I never knew exactly the right way to detect it. After we got our solar panels I was doing research on how to track power usage and came across an article about current sensors and had the idea that I could hook up a current sensor to each appliance and watch the output voltage to know if the appliance was running. While trying to find a decent sensor I stumbled across a current switch which was more or less the same idea but had everything in one package - when the current was over a certain threshold the switch would close and that could be easily detected.
My first thought was to use a [PowerState Tail](http://www.powerswitchtail.com/powerstate-tail) but only a 120V version was available - there was nothing like it I could use for the 240V of the dryer. Eventually I settled on a [Dwyer Miniature Current Switch](https://smile.amazon.com/gp/product/B00I9IFJOM/ref=oh_aui_search_detailpage?ie=UTF8&psc=1) and I'd use one each for both the washer and dryer just to be consistent.

View File

@@ -8,6 +8,8 @@ tags:
The software side of [LaundryMonitor](https://github.com/ckaczor/LaundryMonitor) is currently pretty straightforward. The [C.H.I.P.](https://getchip.com/pages/chip) runs a Node.js application that keeps track of a GPIO pin for each current switch - when the switch is closed the appliance is on and when the switch is open the appliance is off. The application exposes a websocket that applications like [HomeStatusWindow](https://github.com/ckaczor/HomeStatusWindow) can watch and messages are sent to a family Telegram channel.
<!-- excerpt -->
[![](images/HomeStatusWindow.png)](images/HomeStatusWindow.png)
[![](images/LaundryBot-238x300.png)](images/LaundryBot.png)

View File

@@ -8,6 +8,8 @@ tags:
Next up in the "floating status window" category is [SystemTemperatureStatusWindow](https://github.com/ckaczor/SystemTemperatureStatusWindow). This one does exactly what it says on the tin - it shows various system temperature values.
<!-- excerpt -->
[![](images/SystemTemperatureStatusWindow.png)](images/SystemTemperatureStatusWindow.png)
The sensor data is read using the [Open Hardware Monitor](http://openhardwaremonitor.org/) library which is pretty straightforward - the one catch is that it requires running as an administrator and getting a UAC prompt each time the application starts got a bit annoying after a while.

View File

@@ -8,6 +8,8 @@ tags:
One of the oldest projects I'm still working on today is my weather station. I had always wanted a weather station but it seemed boring to just install something on the roof, stick an LCD display on the wall somewhere, and then forget about it - I wanted something I could build, expand on, and write my own software for.
<!-- excerpt -->
At some point I ran across a [weather station](http://www.eham.net/reviews/detail/4643) from AAG Electronica - it was relatively cheap, had a bunch of sensors, and ran on the Dallas Semiconductor (now Maxim Integrated) [1-Wire network](https://www.maximintegrated.com/en/products/digital/one-wire.html). It was pretty much everything that I was looking for so I bought one, mounted it on the chimney, and set about writing an application for it.
At the time I was starting to learn C# and decided this would make a perfect learning project. There were a few examples for using the 1-Wire hardware (mostly in Java from what I remember) but I was able to access the driver functions from C# and started to get things working. At the lowest level there was a lot of bit manipulation but once that was going I was able to start building the application up from there.

View File

@@ -7,6 +7,8 @@ tags:
I'm going to take a break from status windows for a little bit to cover my [WorkIndicator](https://github.com/ckaczor/WorkIndicator) project.
<!-- excerpt -->
I've been working remotely for almost 14 years now and my family found it hard to tell when I was working or on the phone. It often looks the same whether I'm working or not - I'm sitting at my computer, sometimes with my headset on. At some point I came across a [blog post](https://www.hanselman.com/blog/IsDaddyOnACallABusyLightPresenceIndicatorForLyncForMyHomeOffice.aspx) by Scott Hanselman that described hooking up a status light to Lync and I was inspired to create something similar.
The first task was to find something I could use as a status light - after some research I settled on a [USB HID Green/Yellow/Red Visual Indicator](https://www.delcomproducts.com/productdetails.asp?PartNumber=907241) from Delcom. I liked that it had a stoplight design and it came with a C# sample - perfect!

View File

@@ -1,3 +1,3 @@
export default {
layout: "layouts/home.njk"
layout: 'layouts/home.njk'
};

View File

@@ -3,28 +3,6 @@ const eleventyNavigation = {
key: "Home",
order: 1
};
const numberOfLatestPostsToShow = 3;
---
{% set postsCount = collections.posts | length %}
{% set latestPostsCount = postsCount | min(numberOfLatestPostsToShow) %}
<h1>Latest {{ latestPostsCount }} Post{% if latestPostsCount != 1 %}s{% endif %}
</h1>
{% set postslist = collections.posts | head(-1 * numberOfLatestPostsToShow) %}
{% set postslistCounter = postsCount %}
{% include "postslist.njk" %}
{% set morePosts = postsCount - numberOfLatestPostsToShow %}
{% if morePosts > 0 %}
<p>{{ morePosts }} more post{% if morePosts != 1 %}s{% endif %} can be found in <a href="blog.njk">the archive</a>.</p>
{% endif %}
{# List every content page in the project #}
{#
<ul>
{%- for entry in collections.all %}
<li><a href="{{ entry.url }}"><code>{{ entry.url }}</code></a></li>
{%- endfor %}
</ul>
#}
{% set postslist = collections.posts %}
{% include "postslist.njk" %}

View File

@@ -45,6 +45,11 @@ export default async function (eleventyConfig) {
toFileDirectory: "dist"
});
eleventyConfig.setFrontMatterParsingOptions({
excerpt: true,
excerpt_separator: "<!-- excerpt -->"
});
// Official plugins
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
preAttributes: { tabindex: 0 }

View File

@@ -1,6 +1,6 @@
/* Defaults */
:root {
--font-family: Roboto, -apple-system, system-ui, sans-serif;
--font-family: Roboto, sans-serif;
--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,
@@ -95,10 +95,15 @@ a[href]:active {
color: var(--text-color-link-active);
}
main,
footer {
main {
padding: 1rem;
}
footer {
padding-bottom: 1rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 0.75rem;
}
main :first-child {
margin-top: 0;
}
@@ -107,7 +112,7 @@ header {
border-bottom: 1px dashed var(--color-gray-20);
}
header:after {
content: "";
content: '';
display: table;
clear: both;
}
@@ -116,7 +121,7 @@ header:after {
display: flex;
justify-content: space-between;
gap: 0.5em 1em;
list-style: "";
list-style: '';
border-top: 1px dashed var(--color-gray-20);
padding: 1em 0;
}
@@ -139,7 +144,7 @@ pre,
code {
font-family: var(--font-family-monospace);
}
pre:not([class*="language-"]) {
pre:not([class*='language-']) {
margin: 0.5em 0;
line-height: 1.375; /* 22px /16 */
-moz-tab-size: var(--syntax-tab-size);
@@ -190,7 +195,7 @@ header {
.nav-item a[href]:not(:hover) {
text-decoration: none;
}
.nav a[href][aria-current="page"] {
.nav a[href][aria-current='page'] {
text-decoration: underline;
}
@@ -198,22 +203,21 @@ header {
.postlist {
list-style: none;
padding: 0;
padding-left: 1.5rem;
}
.postlist-item {
display: flex;
flex-wrap: wrap;
align-items: baseline;
counter-increment: start-from -1;
margin-bottom: 1em;
margin-bottom: 2em;
}
.postlist-item:last-child {
margin-bottom: 0em;
}
.postlist-item:before {
display: inline-block;
pointer-events: none;
content: "" counter(start-from, decimal-leading-zero) ". ";
line-height: 100%;
text-align: right;
margin-left: -1.5rem;
}
.postlist-date,
.postlist-item:before {
@@ -222,14 +226,27 @@ header {
}
.postlist-date {
word-spacing: -0.5px;
flex-basis: 100%;
}
.postlist-link {
font-size: 1.1875em; /* 19px /16 */
font-weight: 700;
flex-basis: calc(100% - 1.5rem);
padding-left: 0.25em;
padding-right: 0.5em;
text-decoration: none;
}
.postlist-read-more {
text-decoration: none;
font-size: 0.8125em;
flex-basis: 100%;
}
.postlist-read-more:hover {
text-decoration: underline;
}
.postlist-link:hover {
text-decoration: underline;
text-underline-position: from-font;
text-underline-offset: 0;
text-decoration-thickness: 1px;
@@ -238,6 +255,28 @@ header {
font-weight: bold;
}
.postlist-byline {
flex-basis: 100%;
}
.postlist-tags {
display: inline-flex;
align-items: center;
justify-content: center;
list-style-type: none;
gap: 0.5em;
font-size: 0.8125em;
padding-inline-start: 10px;
}
.postlist-tag {
text-decoration: none;
}
.postlist-tag:hover {
text-decoration: underline;
}
/* Tags */
.post-tag {
display: inline-flex;

View File

@@ -1,18 +0,0 @@
/* Message Box */
.message-box {
--color-message-box: #ffc;
display: block;
background-color: var(--color-message-box);
color: var(--color-gray-90);
padding: 1em 0.625em; /* 16px 10px /16 */
}
.message-box ol {
margin-top: 0;
}
@media (prefers-color-scheme: dark) {
.message-box {
--color-message-box: #082840;
}
}

View File

@@ -2,7 +2,7 @@
* New diff- syntax
*/
pre[class*="language-diff-"] {
pre[class*='language-diff-'] {
--eleventy-code-padding: 1.25em;
padding-left: var(--eleventy-code-padding);
padding-right: var(--eleventy-code-padding);

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

BIN
public/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB