Merge branch 'main' into drafts

This commit is contained in:
John Bowdre 2024-08-16 14:43:44 -05:00
commit 99067ebc8b
12 changed files with 240 additions and 114 deletions

View file

@ -126,17 +126,17 @@ opacity: 1;
Insert prompt indicators on interactive shells. Insert prompt indicators on interactive shells.
*/ */
.cmd::before { .cmd::before {
color: var(--base07); color: var(--user-prompt);
content: "$ "; content: "$ ";
} }
.cmd_root::before { .cmd_root::before {
color: var(--base08); color: var(--root-prompt);
content: "# "; content: "# ";
} }
.cmd_pwsh::before { .cmd_pwsh::before {
color: var(--base07); color: var(--user-prompt);
content: "PS> "; content: "PS> ";
} }

40
assets/js/set-theme.js Normal file
View file

@ -0,0 +1,40 @@
const toggleButton = document.getElementById('themeToggle');
const htmlElement = document.documentElement;
function setTheme(theme) {
htmlElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
updateToggleButton(theme);
}
function updateToggleButton(theme) {
toggleButton.setAttribute('aria-checked', theme === 'dark');
}
function getPreferredTheme() {
const storedTheme = localStorage.getItem('theme');
if (storedTheme) {
return storedTheme;
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
// Ensure the toggle button state is correct on load
document.addEventListener('DOMContentLoaded', () => {
updateToggleButton(getPreferredTheme());
});
// Listen for toggle button clicks
toggleButton.addEventListener('click', () => {
const currentTheme = htmlElement.getAttribute('data-theme') || getPreferredTheme();
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
setTheme(newTheme);
});
// Listen for system preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
const newTheme = e.matches ? 'dark' : 'light';
setTheme(newTheme);
}
});

View file

@ -110,6 +110,7 @@ taglines = [
"there's no place like $HOME", "there's no place like $HOME",
"time jumped backwards, rotating", "time jumped backwards, rotating",
"tonight we test in prod", "tonight we test in prod",
"unable to decrypt error",
"unable to open display", "unable to open display",
"undefined reference to function", "undefined reference to function",
"unexpected token", "unexpected token",

View file

@ -1,7 +1,7 @@
--- ---
title: "/changelog" title: "/changelog"
date: "2024-05-26T21:19:08Z" date: "2024-05-26T21:19:08Z"
lastmod: "2024-08-04T22:30:43Z" lastmod: "2024-08-15T21:21:05Z"
description: "Maybe I should keep a log of all my site-related tinkering?" description: "Maybe I should keep a log of all my site-related tinkering?"
featured: false featured: false
toc: false toc: false
@ -10,6 +10,9 @@ categories: slashes
--- ---
*Running list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).* *Running list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).*
**2024-08-15:**
- Implemented light/dark theme toggle
**2024-08-04:** **2024-08-04:**
- Dynamically build `robots.txt` based on [ai.robots.txt](https://github.com/ai-robots-txt/ai.robots.txt) - Dynamically build `robots.txt` based on [ai.robots.txt](https://github.com/ai-robots-txt/ai.robots.txt)

View file

@ -26,7 +26,7 @@
{{- if and (gt $ageDays 365) (not .Params.timeless) -}} {{- if and (gt $ageDays 365) (not .Params.timeless) -}}
<br> <br>
<div class="notice note"> <div class="notice note">
<p class="first notice-title"><span class="icon-notice baseline"><svg><use href="#note-notice"></use></svg></span>Technology keeps moving but this post has not.</p> <p class="first notice-title"><span class="icon-notice baseline"><svg id="note-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet"><path d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/></svg></span>Technology keeps moving but this post has not.</p>
What you're about to read hasn't been updated in more than a year. The information may be out of date. Let me know if you see anything that needs fixing. What you're about to read hasn't been updated in more than a year. The information may be out of date. Let me know if you see anything that needs fixing.
</div> </div>
{{- end -}} {{- end -}}

View file

@ -1,7 +1,7 @@
{{ with .Site.Params.about }} {{ with .Site.Params.about }}
<div class="aside__about"> <div class="aside__about">
{{ with .logo }}<img class="about__logo" src="{{ . | absURL }}" alt="Logo">{{ end }} {{ with .logo }}<img class="about__logo" src="{{ . | absURL }}" alt="Logo">{{ end }}
<h1 class="about__title">{{ .title }}&nbsp;<a href="/feed.xml" aria-label="RSS"><i class="fa-solid fa-square-rss"></i></a>&nbsp;</h1> <h1 class="about__title">{{ .title }}&nbsp;<a href="/feed.xml" aria-label="RSS"><i class="fa-solid fa-square-rss"></i></a></h1>
{{ partial "tagline.html" . }} {{ partial "tagline.html" . }}
<br> <br>
<a href="/about/"><i class="fa-regular fa-user"></i></a>&nbsp;<a href="/about/">{{ site.Params.Author.name }}</a> <a href="/about/"><i class="fa-regular fa-user"></i></a>&nbsp;<a href="/about/">{{ site.Params.Author.name }}</a>

View file

@ -15,3 +15,7 @@
{{ $jsCopy := resources.Get "js/code-copy-button.js" | minify }} {{ $jsCopy := resources.Get "js/code-copy-button.js" | minify }}
<script src="{{ $jsCopy.RelPermalink }}" async></script> <script src="{{ $jsCopy.RelPermalink }}" async></script>
{{ end }} {{ end }}
<!-- theme switch -->
{{ $themeToggle := resources.Get "js/set-theme.js" | minify }}
<script src="{{ $themeToggle.RelPermalink }}"></script>

View file

@ -21,8 +21,20 @@
{{ partialCached "favicon" . }} {{ partialCached "favicon" . }}
{{ partial "opengraph" . }} {{ partial "opengraph" . }}
<!-- load theme preference asap -->
<script>
(function() {
var savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.documentElement.setAttribute('data-theme', savedTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
document.documentElement.setAttribute('data-theme', 'light');
}
})();
</script>
<!-- FontAwesome <https://fontawesome.com/> --> <!-- FontAwesome <https://fontawesome.com/> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" integrity="sha512-1sCRPdkRXhBV2PBLUdRb4tMg1w2YPf37qatUFeS7zlBy7jJI8Lf4VHwWfZZfpXtYSLy85pkm9GaYVYMfw5BC1A==" crossorigin="anonymous" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" />
<!-- ForkAwesome <https://forkaweso.me/> --> <!-- ForkAwesome <https://forkaweso.me/> -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css" integrity="sha256-XoaMnoYC5TH6/+ihMEnospgm0J1PM/nioxbOUdnM8HY=" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css" integrity="sha256-XoaMnoYC5TH6/+ihMEnospgm0J1PM/nioxbOUdnM8HY=" crossorigin="anonymous">

View file

@ -7,4 +7,8 @@
{{ end }} {{ end }}
</ul> </ul>
</nav> </nav>
<button id="themeToggle" class="theme-toggle" aria-label="Toggle light/dark theme" title="Toggle light/dark theme">
<svg class="theme-toggle__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M448 256c0-106-86-192-192-192l0 384c106 0 192-86 192-192zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256z"/>
</svg>
</button>

View file

@ -1,9 +1,113 @@
/* color and font overrides */ /* define fonts */
:root { :root {
--code: var(--base06);
--font-monospace: 'Berkeley Mono', 'IBM Plex Mono', 'Cascadia Mono', 'Roboto Mono', 'Source Code Pro', 'Fira Mono', 'Courier New', monospace; --font-monospace: 'Berkeley Mono', 'IBM Plex Mono', 'Cascadia Mono', 'Roboto Mono', 'Source Code Pro', 'Fira Mono', 'Courier New', monospace;
} }
/* dark/light theming */
:root{
/* Default dark theme */
--bg: var(--dark-base00);
--code: var(--dark-base06);
--fg: var(--dark-base05);
--highlight: var(--dark-base0A);
--hover: var(--dark-base0C);
--inner-bg: var(--dark-base02);
--link: var(--dark-base0D);
--logo-text: var(--dark-base09);
--logo: var(--dark-base0B);
--muted: var(--dark-base03);
--off-bg: var(--dark-base01);
--off-fg: var(--dark-base04);
--root-prompt: var(--dark-base08);
--user-prompt: var(--dark-base07);
}
:root[data-theme="light"] {
--bg: var(--light-base00);
--off-bg: var(--light-base01);
--inner-bg: var(--light-base02);
--muted: var(--light-base03);
--off-fg: var(--light-base04);
--fg: var(--light-base05);
--code: var(--light-base06);
--user-prompt: var(--light-base07);
--root-prompt: var(--light-base08);
--logo-text: var(--light-base09);
--highlight: var(--light-base0A);
--logo: var(--light-base0B);
--hover: var(--light-base0C);
--link: var(--light-base0D);
}
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) {
--bg: var(--light-base00);
--off-bg: var(--light-base01);
--inner-bg: var(--light-base02);
--muted: var(--light-base03);
--off-fg: var(--light-base04);
--fg: var(--light-base05);
--code: var(--light-base06);
--user-prompt: var(--light-base07);
--root-prompt: var(--light-base08);
--logo-text: var(--light-base09);
--highlight: var(--light-base0A);
--logo: var(--light-base0B);
--hover: var(--light-base0C);
--link: var(--light-base0D);
}
}
body {
transition: background-color 0.3s ease, color 0.3s ease;
}
.theme-toggle {
position: absolute;
top: 1rem;
right: 1rem;
background: none;
border: none;
cursor: pointer;
padding: 0;
width: 2rem;
height: 2rem;
z-index: 1000;
transition: opacity 0.3s ease;
}
.theme-toggle:hover {
opacity: 0.7;
}
.theme-toggle:focus {
outline: none;
}
.theme-toggle:focus-visible {
outline: 2px solid var(--hover);
outline-offset: 2px;
}
.theme-toggle__icon {
width: 100%;
height: 100%;
transition: transform 0.3s ease, fill 0.3s ease;
fill: var(--off-fg);
}
.theme-toggle:hover .theme-toggle__icon {
fill: var(--hover);
}
[data-theme="dark"] .theme-toggle__icon {
transform: rotate(180deg);
}
.page__nav ul {
padding-right: 3rem;
}
/* load preferred font */ /* load preferred font */
@font-face { @font-face {
font-family: 'Berkeley Mono'; font-family: 'Berkeley Mono';
@ -30,7 +134,7 @@
/* logo tweaks */ /* logo tweaks */
.page__logo { .page__logo {
color: var(--off-fg); color: var(--logo-text);
} }
.page__logo-inner { .page__logo-inner {
@ -70,59 +174,24 @@
/* Notice CSS Built on hugo-notice by Nicolas Martignoni: https://github.com/martignoni/hugo-notice */ /* Notice CSS Built on hugo-notice by Nicolas Martignoni: https://github.com/martignoni/hugo-notice */
.notice { .notice {
--root-color: #444; --notice-title-color: #fff;
--root-background: #eff; --notice-warn-color: #c33;
--title-color: #fff; --notice-info-color: #fb7;
--title-background: #7bd; --notice-note-color: #6be;
--warning-title: #c33; --notice-tip-color: #5a5;
--warning-content: #fee;
--info-title: #fb7;
--info-content: #fec;
--note-title: #6be;
--note-content: #e7f2fa;
--tip-title: #5a5;
--tip-content: #efe;
}
@media (prefers-color-scheme: dark) { --notice-padding: 18px;
.notice { --notice-line-height: 24px;
--root-color: #ddd; --notice-margin-bottom: 24px;
--root-background: #eff; --notice-border-radius: 4px;
--title-color: #fff; --notice-title-margin: 12px;
--title-background: #7bd; --notice-bg-opacity: 10%;
--warning-title: #800;
--warning-content: #400;
--info-title: #a50;
--info-content: #420;
--note-title: #069;
--note-content: #023;
--tip-title: #363;
--tip-content: #121;
}
}
body.dark .notice { padding: var(--notice-padding);
--root-color: #ddd; line-height: var(--notice-line-height);
--root-background: #eff; margin-bottom: var(--notice-margin-bottom);
--title-color: #fff; border-radius: var(--notice-border-radius);
--title-background: #7bd; color: var(--fg);
--warning-title: #800;
--warning-content: #400;
--info-title: #a50;
--info-content: #420;
--note-title: #069;
--note-content: #023;
--tip-title: #363;
--tip-content: #121;
}
.notice {
padding: 18px;
line-height: 24px;
margin-bottom: 24px;
border-radius: 4px;
color: var(--root-color);
background: var(--root-background);
} }
.notice p:last-child { .notice p:last-child {
@ -130,45 +199,23 @@ body.dark .notice {
} }
.notice-title { .notice-title {
margin: -18px -18px 12px; margin: calc(-1 * var(--notice-padding));
padding: 4px 18px; margin-bottom: var(--notice-title-margin);
border-radius: 4px 4px 0 0; padding: 4px var(--notice-padding);
border-radius: var(--notice-border-radius) var(--notice-border-radius) 0 0;
font-weight: 700; font-weight: 700;
color: var(--title-color); color: var(--notice-title-color);
background: var(--title-background);
} }
.notice.warning .notice-title { .notice.warning .notice-title { background: var(--notice-warning-color); }
background: var(--warning-title); .notice.info .notice-title { background: var(--notice-info-color); }
} .notice.note .notice-title { background: var(--notice-note-color); }
.notice.tip .notice-title { background: var(--notice-tip-color); }
.notice.warning { .notice.warning { background: color-mix(in srgb, var(--notice-warning-color) var(--notice-bg-opacity), transparent); }
background: var(--warning-content); .notice.info { background: color-mix(in srgb, var(--notice-info-color) var(--notice-bg-opacity), transparent); }
} .notice.note { background: color-mix(in srgb, var(--notice-note-color) var(--notice-bg-opacity), transparent); }
.notice.tip { background: color-mix(in srgb, var(--notice-tip-color) var(--notice-bg-opacity), transparent); }
.notice.info .notice-title {
background: var(--info-title);
}
.notice.info {
background: var(--info-content);
}
.notice.note .notice-title {
background: var(--note-title);
}
.notice.note {
background: var(--note-content);
}
.notice.tip .notice-title {
background: var(--tip-title);
}
.notice.tip {
background: var(--tip-content);
}
.icon-notice { .icon-notice {
display: inline-flex; display: inline-flex;

View file

@ -2,20 +2,35 @@
*/ */
:root { :root {
--base00: #090909; /* bg */ /* dark theme colors */
--base01: #1c1c1c; /* off-bg */ --dark-base00: #090909; /* bg */
--base02: #292929; /* inner-bg */ --dark-base01: #1c1c1c; /* off-bg */
--base03: #6d6c6c; /* muted */ --dark-base02: #292929; /* inner-bg */
--base04: #abaaaa; /* off-fg */ --dark-base03: #6d6c6c; /* muted */
--base05: #d8d8d8; /* fg */ --dark-base04: #abaaaa; /* off-fg */
--base06: #75f558; /* code */ --dark-base05: #d8d8d8; /* fg */
--base07: #5f8700; /* user prompt */ --dark-base06: #75f558; /* code */
--base08: #ab4642; /* root prompt */ --dark-base07: #5f8700; /* user prompt */
--base09: #dc9656; --dark-base08: #ab4642; /* root prompt */
--base0A: #f7ca88; /* highlight */ --dark-base09: #abaaaa; /* logo text */
--base0B: #682523; /* logo */ --dark-base0A: #f7ca88; /* highlight */
--base0C: #ab2321; /* hover */ --dark-base0B: #682523; /* logo */
--base0D: #d36060; /* link */ --dark-base0C: #ab2321; /* hover */
--base0E: #ba8baf; --dark-base0D: #d36060; /* link */
--base0F: #a16946;
/* light theme colors */
--light-base00: #ffffff; /* bg */
--light-base01: #f0f0f0; /* off-bg */
--light-base02: #dbdbdb; /* inner-bg */
--light-base03: #909090; /* muted */
--light-base04: #707070; /* off-fg */
--light-base05: #303030; /* fg */
--light-base06: #2a8f1f; /* code */
--light-base07: #3f5900; /* user prompt */
--light-base08: #c23d3d; /* root prompt */
--light-base09: #f0f0f0; /* logo-text */
--light-base0A: #d4a960; /* highlight */
--light-base0B: #af3a37; /* logo */
--light-base0C: #c62a28; /* hover */
--light-base0D: #a04545; /* link */
} }

View file

@ -11,7 +11,7 @@ module.exports = {
// Which theme you want to use. You can find all of the themes at // Which theme you want to use. You can find all of the themes at
// https://torchlight.dev/docs/themes. // https://torchlight.dev/docs/themes.
theme: 'synthwave-84', theme: 'material-theme-lighter',
// The Host of the API. // The Host of the API.
host: 'https://api.torchlight.dev', host: 'https://api.torchlight.dev',