Compare commits

..
26 Commits
Author SHA1 Message Date
inherentlee 2e26cefab2 tiny tweak to prevent gap
continuous-integration/drone/push Build is passing
2026-09-20 19:04:19 -07:00
inherentlee 870a6e5e0f prevent blockquotes interferring with toc
continuous-integration/drone/push Build is passing
2026-09-20 19:01:54 -07:00
inherentlee be364d7644 it's important that the comment have a slant rhyme
continuous-integration/drone/push Build is passing
2026-09-20 18:50:52 -07:00
inherentlee 06bcfc1522 toc tree styling
continuous-integration/drone/push Build is passing
2026-09-20 18:46:09 -07:00
inherentlee dd1943bcdd li line height matches p line height
continuous-integration/drone/push Build is passing
2026-09-20 15:13:17 -07:00
inherentlee bfa91ea19f big ol toc update
continuous-integration/drone/push Build is passing
2026-09-20 15:07:49 -07:00
inherentlee b4fbeffc41 new font omg
continuous-integration/drone/push Build is passing
2026-09-19 17:40:10 -07:00
inherentlee 25cf8a38ec fix sitemap size 2026-09-18 12:30:23 -07:00
inherentlee 5724f509a0 update resume
continuous-integration/drone/push Build is passing
2026-09-18 08:48:30 -07:00
inherentlee fe6956aaa3 mark down framer for complex keyboard interactions
continuous-integration/drone/push Build is passing
2026-09-17 17:59:08 -07:00
inherentlee 846ef7538f note re dropdowns in framer
continuous-integration/drone/push Build is passing
2026-09-17 17:57:33 -07:00
inherentlee f8aacdc85d note about dropdowns
continuous-integration/drone/push Build is passing
2026-09-17 17:04:46 -07:00
inherentlee 776218805a more notes about framer
continuous-integration/drone/push Build is passing
2026-09-17 12:03:26 -07:00
inherentlee 91c7f14113 add instructions just for completeness
continuous-integration/drone/push Build is passing
2026-09-17 08:18:27 -07:00
inherentlee 8bcdaeff52 idk these notes were wrong i guess 2026-09-17 08:16:38 -07:00
inherentlee 3e766eb519 find a few more target=_blank bits
continuous-integration/drone/push Build is passing
2026-09-17 08:02:47 -07:00
inherentlee 2ad41daa2e make leatherworking zine a draft
continuous-integration/drone/push Build is passing
2026-09-17 07:56:09 -07:00
inherentlee 7b248c24b9 Merge branch 'leatherworking-zine' 2026-09-17 07:55:34 -07:00
inherentlee abec70c655 add missing page 2026-09-17 07:55:26 -07:00
inherentlee 2d35768db9 preliminary squarespace findings
continuous-integration/drone/push Build is passing
2026-09-16 11:06:40 -07:00
inherentlee 30498307c8 npm audit fix
continuous-integration/drone/push Build is passing
2026-09-15 18:05:04 -07:00
inherentlee 953f651c4f draft
continuous-integration/drone/push Build is passing
2026-09-15 14:47:53 -07:00
inherentlee ee0a39333d package-lock.json update
continuous-integration/drone/push Build is passing
2026-09-14 18:17:10 -07:00
inherentlee a2fd1cb797 package.lock updates? 2026-09-14 18:11:59 -07:00
inherentlee 9889cf4adb fix og metadata
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is failing
2026-09-14 10:38:11 -07:00
inherentlee a3b9d20dfb small style and word fixes to framer accessibility 2026-09-12 10:53:25 -07:00
43 changed files with 978 additions and 159 deletions
+14 -6
View File
@@ -2,14 +2,22 @@
Lee Cattarin's personal website, v2. Built on Eleventy.
## Pulling from git repo with NPM
## Install
Apparently this works differently in WSL vs Linux? Fuck me, I guess.
```sh
npm i
# or
npm install
```
### WSL2
## Run locally
> "@zachleat/heading-anchors": "https://github.com/lee0c/heading-anchors/tarball/main",
```sh
npm run dev
```
### Linux
## Build website
> "@zachleat/heading-anchors": "github:lee0c/heading-anchors"
```sh
npm run build
```
+4 -1
View File
@@ -13,8 +13,11 @@
<meta property="og:site_name" content="{{ metadata.title }}" />
<meta property="og:url" content="{{ metadata.url }}{{ page.url }}" />
{% if image %}
<meta property="og:image" content="/img/{{ image.src | toOgFilename }}" />
<meta property="og:image" content="{{ metadata.url }}/img/{{ image.src | toOgFilename }}" />
<meta property="og:image:alt" content="{{ image.alt }}" />
{% else %}
<meta property="og:image" content="{{ metadata.url }}/favicon.ico" />
<meta property="og:image:alt" content="a teal bird icon" />
{% endif %}
<meta name="generator" content="{{ eleventy.generator }}">
+13
View File
@@ -0,0 +1,13 @@
---
layout: post.njk
---
{% css %}{% include "css/post-toc.css" %}{% endcss %}
<aside id="toc">
<details>
<summary><h2>table of contents</h2></summary>
{{ content | toc | safe }}
</details>
</aside>
{{ content | safe }}
+1
View File
@@ -111,6 +111,7 @@
grid-area: h2;
padding: .25rem .5rem;
text-transform: uppercase;
font-family: var(--font-family);
font-size: 1.5rem;
color: var(--color-primary);
border-radius: 1rem 1rem 0 0;
+20 -9
View File
@@ -1,7 +1,17 @@
@font-face {
font-family: "Peritel";
src:
url("/fonts/Peritel/Peritel-Regular.woff2") format("woff2"),
url("/fonts/Peritel/Peritel-Regular.otf") format("opentype");
}
:root {
color-scheme: light dark;
--font-family: 'Atkinson Hyperlegible Next', sans-serif;
/* if you change the header font, go to post-toc.css and fuck about with the width
of the table of contents */
--font-family-headers: 'Peritel', 'Atkinson Hyperlegible Next', sans-serif;
--font-family-code: 'Atkinson Hyperlegible Mono', monospace;
--color-dark: #2e303e;
@@ -59,7 +69,6 @@
}
/* Base */
* {
box-sizing: border-box;
margin: 0;
@@ -95,11 +104,13 @@ main {
h1, h2, h3, h4, h5, h6 {
line-height: 1.25;
color: var(--color-teal);
font-family: var(--font-family-headers);
letter-spacing: 0.1rem;
}
h1 {
margin-top: 3rem;
font-size: 3.5rem;
font-size: 3.7rem;
text-align: center;
}
@@ -109,23 +120,23 @@ h2, h3, h4, h5, h6 {
h2 {
margin-top: 2rem;
font-size: 2.2rem;
font-size: 2.35rem;
}
h3 {
margin-top: 1.5rem;
font-size: 1.6rem;
font-size: 1.7rem;
}
@media (max-width: 650px) {
h1 { font-size: 2.8rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.35rem; }
h1 { font-size: 2.95rem; }
h2 { font-size: 1.9rem; }
h3 { font-size: 1.4rem; }
}
h4, h5, h6 {
margin-top: 1rem;
font-size: 1.2rem;
font-size: 1.25rem;
}
/* Images */
@@ -201,7 +212,7 @@ ul, ol, dl, li {
}
li {
line-height: 1.2;
line-height: 1.4;
margin-top: .65rem;
margin-bottom: .65rem;
}
+94
View File
@@ -0,0 +1,94 @@
#toc {
float: right;
margin: 1rem 0 1.5rem 1.5rem;
/* 23rem is the width of the words 'table of contents' in my header font */
/* yes, it's a bit hacky */
width: min(calc(100% - 1.5rem), 23rem);
}
@media (max-width: 850px) {
#toc {
float: unset;
margin-top: 2rem;
margin-left: .5rem;
width: calc(100% - .5rem);
}
}
#toc details {
border: thick solid var(--color-pink);
border-radius: 1rem;
margin-top: 1rem;
background-color: var(--color-bg);
}
#toc summary {
position: relative;
top: -1.5rem;
left: -.75rem;
width: fit-content;
background: var(--color-bg);
border-radius: .5rem;
cursor: pointer;
}
#toc summary:focus-visible {
outline: .15rem solid var(--color-teal);
}
#toc summary::marker {
font-size: 2.35rem;
}
#toc h2 {
margin-top: 0;
display: inline;
line-height: normal;
}
#toc nav {
position: relative;
top: -1.25rem;
}
/* my baby my child my `tree` list style */
#toc ol,
#toc li {
margin-block: 0;
}
#toc ol {
margin-left: 0;
list-style: none;
}
#toc li {
border-left: .095rem solid var(--color-pink);
line-height: 1.15;
margin-left: 1.5rem;
}
#toc li::before {
content: '├─';
color: var(--color-pink);
position: relative;
left: -.34rem;
}
#toc li:last-child {
border-left-color: transparent;
}
#toc li:last-child::before {
/* Technically, we could use this content for all of them, but doing the full
bar for the non-last-childs keeps the border a *smidge* more consistent for
different levels of magnification */
content: '└─';
}
/* underlines are unnecessary in this context */
#toc a {
text-decoration: none;
color: var(--color-blue);
font-weight: bold;
}
+15 -7
View File
@@ -1,11 +1,13 @@
import { IdAttributePlugin } from "@11ty/eleventy";
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
import eleventyNavigationPlugin from "@11ty/eleventy-navigation";
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import toc from "eleventy-plugin-nesting-toc";
import { attrs } from "@mdit/plugin-attrs";
import { markdownitLinkAttributes } from 'markdown-it-link-attributes';
import markdownitIdAttributes from "markdown-it-anchor";
import path from "node:path";
import { execSync } from 'child_process';
@@ -18,7 +20,7 @@ export default async function(eleventyConfig) {
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(attrs));
/* Markdown apply target="_blank" to all external links */
const milaOptions = {
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(markdownitLinkAttributes, {
matcher(href) {
return href.match(/^https?:\/\//);
},
@@ -26,8 +28,13 @@ export default async function(eleventyConfig) {
target: "_blank",
rel: "external",
},
};
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(markdownitLinkAttributes, milaOptions));
}));
/* Markdown apply ID attributes to headers */
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(markdownitIdAttributes, {
level: [2, 3, 4],
tabIndex: false,
}));
/* Bundles */
/* CSS */
@@ -72,6 +79,7 @@ export default async function(eleventyConfig) {
/* Passthrough */
eleventyConfig
.addPassthroughCopy("favicon.ico")
.addPassthroughCopy("fonts")
.addPassthroughCopy("robots.txt");
/* Plugins */
@@ -127,12 +135,12 @@ export default async function(eleventyConfig) {
/* Navigation */
eleventyConfig.addPlugin(eleventyNavigationPlugin);
/* `id` attributes */
eleventyConfig.addPlugin(IdAttributePlugin);
/* Syntax highlighting */
eleventyConfig.addPlugin(syntaxHighlight);
/* Table of contents */
eleventyConfig.addPlugin(toc);
/* Draft handling */
eleventyConfig.addPreprocessor("drafts", "*", (data, content) => {
if (data.draft) {
+33
View File
@@ -0,0 +1,33 @@
# End User License Agreement (EULA)
This End User License Agreement is a legal agreement between the licensee (you), and the author of this font, Christopher Kirk-Nielsen.
You are granted a perpetual, non-exclusive license to use the font with your purchase.
## By downloading or purchasing this font, you agree to the following terms:
**For use on a website**
Use on any website owned or under the licensee's control, no pageview limits.
**For use in an app**
App embed allowed for 1 app. Another app = another license.
**Distribution**
The font may not be redistributed.
**Personal modification**
The font may be modified for personal use, but cannot be redistributed.
**Do not use the font for hateful purposes**
The font is not allowed to be used in any material promoting hate speech of any kind, including but not limited to: racism, xenophobia, homophobia, sexism, or other types of discrimination.
**Do not use the font with AI**
The font is not allowed to be used in, or in training of, AI/LLMs.
**Use at your own risk**
Any usage of the fonts are at the licensee's own risk.
For ebooks and other commercial use, or any other specific needs, email me to figure something out: chriskirknielsen+fonts[at]gmail.com
Thank you very much for the support!
Christopher Kirk-Nielsen (https://chriskirknielsen.com/fonts/)
Binary file not shown.
Binary file not shown.
+551 -45
View File
@@ -17,8 +17,11 @@
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
"@mdit/plugin-attrs": "^0.24.2",
"@zachleat/heading-anchors": "https://github.com/lee0c/heading-anchors/tarball/main",
"cheerio": "^1.2.0",
"eleventy-plugin-nesting-toc": "^1.3.0",
"lodash-es": "^4.17.23",
"luxon": "^3.7.2",
"markdown-it-anchor": "^10.0.0",
"markdown-it-link-attributes": "https://github.com/lee0c/markdown-it-link-attributes/tarball/main",
"pagefind": "^1.5.2"
}
@@ -299,9 +302,9 @@
}
},
"node_modules/@emnapi/runtime": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
"integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
"integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -397,6 +400,9 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -414,6 +420,9 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -431,6 +440,9 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -465,6 +477,9 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -499,6 +514,9 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -522,6 +540,9 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -545,6 +566,9 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -591,6 +615,9 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -953,9 +980,9 @@
}
},
"node_modules/anymatch/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1084,10 +1111,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true,
"license": "ISC"
},
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1121,6 +1155,201 @@
"node": ">= 10.16.0"
}
},
"node_modules/cheerio": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
"integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
"dev": true,
"license": "MIT",
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
"encoding-sniffer": "^0.2.1",
"htmlparser2": "^10.1.0",
"parse5": "^7.3.0",
"parse5-htmlparser2-tree-adapter": "^7.1.0",
"parse5-parser-stream": "^7.1.2",
"undici": "^7.19.0",
"whatwg-mimetype": "^4.0.0"
},
"engines": {
"node": ">=20.18.1"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
}
},
"node_modules/cheerio-select": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-select": "^5.1.0",
"css-what": "^6.1.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/cheerio-select/node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dev": true,
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/cheerio-select/node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/cheerio-select/node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/cheerio-select/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/cheerio/node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dev": true,
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/cheerio/node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/cheerio/node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/cheerio/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/cheerio/node_modules/htmlparser2": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
"dev": true,
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
"entities": "^7.0.1"
}
},
"node_modules/cheerio/node_modules/htmlparser2/node_modules/entities": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -1208,6 +1437,95 @@
"dev": true,
"license": "MIT"
},
"node_modules/css-select": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-select/node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dev": true,
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/css-select/node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/css-select/node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/css-select/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/css-what": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -1338,6 +1656,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/eleventy-plugin-nesting-toc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eleventy-plugin-nesting-toc/-/eleventy-plugin-nesting-toc-1.3.0.tgz",
"integrity": "sha512-WZzVkz28nw3A0DpJFQWXZzQxniyjvOZKxVix5x7WVAS0H1OD1hYJbR0go/Lr1kK2SrmxfbsUHUlekR+mQPvqMA==",
"dev": true,
"license": "ISC",
"dependencies": {
"cheerio": "^1.0.0-rc.3"
}
},
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
@@ -1348,6 +1676,20 @@
"node": ">= 0.8"
}
},
"node_modules/encoding-sniffer": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
"integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
"dev": true,
"license": "MIT",
"dependencies": {
"iconv-lite": "^0.6.3",
"whatwg-encoding": "^3.1.1"
},
"funding": {
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
}
},
"node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
@@ -1536,9 +1878,9 @@
"license": "MIT"
},
"node_modules/flatted": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
"integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
"dev": true,
"license": "ISC"
},
@@ -1607,9 +1949,9 @@
}
},
"node_modules/gray-matter/node_modules/js-yaml": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz",
"integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1684,6 +2026,19 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/image-size": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
@@ -1825,10 +2180,20 @@
}
},
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz",
"integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -1868,19 +2233,29 @@
}
},
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz",
"integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
}
},
"node_modules/liquidjs": {
"version": "10.24.0",
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.24.0.tgz",
"integrity": "sha512-TAUNAdgwaAXjjcUFuYVJm9kOVH7zc0mTKxsG9t9Lu4qdWjB2BEblyVIYpjWcmJLMGgiYqnGNJjpNMHx0gp/46A==",
"version": "10.29.0",
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.29.0.tgz",
"integrity": "sha512-pCVOhs6FLAR8su3ItJ07diN26t6W5dHQRnmTMy8HPyTFuv1+oSCVJIGp5pGjfQyOZfh50KswvKtMTp6p4JEIdw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1906,9 +2281,9 @@
"license": "MIT"
},
"node_modules/lodash-es": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz",
"integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
"dev": true,
"license": "MIT"
},
@@ -1923,15 +2298,25 @@
}
},
"node_modules/markdown-it": {
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz",
"integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==",
"version": "14.3.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.2.tgz",
"integrity": "sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"entities": "^4.5.0",
"linkify-it": "^5.0.2",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
@@ -1940,10 +2325,21 @@
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/markdown-it-anchor": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-10.0.0.tgz",
"integrity": "sha512-Q8g7Z6OBdH3eXF0lujFqukIxUvgCDZcjzCrJxmD6QiEzU1HWR9fVN+Bf6gxmM+0yrPFs+jUw8gNjLmUQqt6Eew==",
"dev": true,
"license": "Unlicense",
"peerDependencies": {
"@types/markdown-it": "*",
"markdown-it": "*"
}
},
"node_modules/markdown-it-link-attributes": {
"version": "4.0.1",
"resolved": "https://github.com/lee0c/markdown-it-link-attributes/tarball/main",
"integrity": "sha512-lbnI/d5TRqlHfP4GJ/Pw8tpcIbqORCwKEB4sqOp4IrzVNHsOsHIL2GBOJsjp1H5Y2phHil4lcbxMdvrx3LUriA==",
"integrity": "sha512-AWUn7JiBi431HkZyXR2MRJxU0wQolHmG/TFCrRSq+w/q4mIzY7c3QKBF1eYEQwXx8IKLdmBVxZA37tp3S1ZkYQ==",
"dev": true,
"license": "MIT"
},
@@ -2024,9 +2420,9 @@
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -2099,6 +2495,19 @@
"node": ">=0.10.0"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/nunjucks": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz",
@@ -2214,6 +2623,62 @@
"dev": true,
"license": "MIT"
},
"node_modules/parse5": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
"dev": true,
"license": "MIT",
"dependencies": {
"entities": "^6.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
"dev": true,
"license": "MIT",
"dependencies": {
"domhandler": "^5.0.3",
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-htmlparser2-tree-adapter/node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/parse5-parser-stream": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
"dev": true,
"license": "MIT",
"dependencies": {
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -2225,9 +2690,9 @@
}
},
"node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
"integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2361,9 +2826,9 @@
}
},
"node_modules/readdirp/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2373,6 +2838,13 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true,
"license": "MIT"
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
@@ -2606,6 +3078,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/undici": {
"version": "7.29.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz",
"integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -2623,10 +3105,34 @@
"dev": true,
"license": "MIT"
},
"node_modules/whatwg-encoding": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
"dev": true,
"license": "MIT",
"dependencies": {
"iconv-lite": "0.6.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/whatwg-mimetype": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/ws": {
"version": "8.19.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
"version": "8.21.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
"integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
"dev": true,
"license": "MIT",
"engines": {
+3
View File
@@ -19,8 +19,11 @@
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
"@mdit/plugin-attrs": "^0.24.2",
"@zachleat/heading-anchors": "https://github.com/lee0c/heading-anchors/tarball/main",
"cheerio": "^1.2.0",
"eleventy-plugin-nesting-toc": "^1.3.0",
"lodash-es": "^4.17.23",
"luxon": "^3.7.2",
"markdown-it-anchor": "^10.0.0",
"markdown-it-link-attributes": "https://github.com/lee0c/markdown-it-link-attributes/tarball/main",
"pagefind": "^1.5.2"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

+2 -1
View File
@@ -7,7 +7,8 @@ eleventyExcludeFromCollections: true
<xsl:template match="/">
<html>
<head>
<title>Sitemap</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>sitemap | hello hello</title>
<style>{% include "css/main.css" %}</style>
</head>
<body>
+17
View File
@@ -0,0 +1,17 @@
---
title: accessibility
---
This website ([leecat.art](/)) aims to be as accessible as possible. To that end, I have tested to the best of my abilities with [NVDA](https://www.nvaccess.org/download/) and [Orca](https://help.gnome.org/orca/index.html), keyboard navigation, and automated review tools.
## Limitations
Because of the nature of a blog with an ever-expanding page list and the fact that I have learned a significant amount in 4 or so years, I cannot guarantee that every article on this site is as accessible as I want it to be. That said, the major pages and navigation have been tested, and I bring my best efforts to every new post.
## Adherence to WCAG 2.2
While I would like to do further structured review and go through the entire list with a finer-tooth comb, my current assessment is that this site meets [WCAG 2.2](https://www.w3.org/WAI/standards-guidelines/wcag/) at least at level AA.
## Feedback
If you meet any barriers in accessing this site, please [contact me](/contact).
+1 -1
View File
@@ -6,7 +6,7 @@ This is v2 of my personal website, built with [{{ eleventy.generator }}](https:/
v1 of this site began in 2022 and was based on [Millennial](https://lenpaul.github.io/Millennial/), a minimalist Jekyll theme for running a blog or publication by Paul Le.
The fonts are [Atkinson Hyperlegible Next and Atkinson Hyperlegible Mono](https://brailleinstitute.org/freefont) for standard text and monospace respectively, specifically designed for low-vision readers to improve character recognition. Also they look neat :)
The header font is [Peritel by Christopher Kirk-Nielsen](https://chriskirknielsen.com/fonts/peritel/). I'm currently trying it on for size, so let me know if you like it - or hate it! The body fonts (and the all-caps headers on the post list pages) are [Atkinson Hyperlegible Next and Atkinson Hyperlegible Mono](https://brailleinstitute.org/freefont) for standard text and monospace respectively, specifically designed for low-vision readers to improve character recognition. Also they look neat :)
The search bar is powered by [Pagefind](https://pagefind.app/). I was guided by [Robb Knight's walkthrough](https://rknight.me/blog/using-pagefind-with-eleventy-for-search/) when setting it up.
+10 -1
View File
@@ -37,6 +37,7 @@ layout: base.njk
<li>GitHub Actions and other pipelines</li>
<li>HTML, CSS, and Javascript</li>
<li>Languages like Go, C, and Python</li>
<li>Relational database theory focused on PostgreSQL</li>
<li>Accessibility knowledge and thoughtful design</li>
</ul>
@@ -56,6 +57,14 @@ layout: base.njk
</p>
<ul>
<li>
<strong>District Dharma
(<a href="https://districtdharma.org/"
target="_blank">districtdharma.org</a>):</strong>
a clean and minimalist homepage for the District Dharma collective,
built in Eleventy with a Mattrbld content management system to allow
for easy editing by the client.
</li>
<li>
<strong>My Liberation Work Has Been Damn Ableist: A Landworker Memoir
(<a href="https://maze-pants.codeberg.page/"
@@ -268,7 +277,7 @@ layout: base.njk
<p>Creates and runs a global event for zine artists on the fediverse, now kicking
off its third year. Coordinates website, physical material shipping and
logistics, payment, and marketing for a 4050 person project. Leads a small team
and delegates appropriate responsibilities.</p>
and delegates appropriate responsibilities.</p>
</div>
<div class="spacer"></div>
+2
View File
@@ -110,6 +110,8 @@ Code blocks can have syntax highlighting:
<h1>Hello, world</h1>
```
### You can even write `headers in monospace`
## Tables
Tables in Markdown are kind of annoying to format. You use the pipe (`|`) character as well as dashes.
+1 -1
View File
@@ -8,4 +8,4 @@ tags:
- gender
---
an incomplete list of books by/for/about queer folks. <a href="https://docs.google.com/document/d/1wqLtUeow59XHp7QfRhGcyufywEvSCh4ed8kYST4F0Yk/edit?usp=sharing" target="_blank">check it out and add your favorites.</a>
an incomplete list of books by/for/about queer folks. [check it out and add your favorites](https://docs.google.com/document/d/1wqLtUeow59XHp7QfRhGcyufywEvSCh4ed8kYST4F0Yk/edit?usp=sharing).
+1
View File
@@ -1,5 +1,6 @@
---
title: butch hands pattern
layout: post-with-toc.njk
image:
src: 2023/butch-hands.jpg
alt: "Hands wearing a pair of pink and grey gloves with convertable mitten tops."
@@ -1,5 +1,6 @@
---
title: backend accessibility
layout: post-with-toc.njk
image:
src: 2023/camelCase-print.jpg
alt: "A carved stamp next to its print. The print reads '#camelCase' in a slightly formal-looking italic font."
@@ -8,7 +9,7 @@ tags:
- software
---
> These notes are from a talk I gave at work. If you think something is missing or incorrect, please let me know!
These notes are from a talk I gave at work. If you think something is missing or incorrect, please let me know!
Backend developers still have users: other developers. We're all human, with human limitations and differences. Design for those limitations and you'll find you improve the end result for everyone.
@@ -3,6 +3,8 @@ title: printing press notes
image:
src: 2023/printing-press.jpg
alt: "An open Speedball Model B printing press, which uses a lever handle to put even pressure on a 6 by 8 inch top plate."
tags:
- reference
---
## specs
@@ -1,5 +1,6 @@
---
title: leatherworking favorites
layout: post-with-toc.njk
image:
src: 2023/leather-harness-wip.jpg
alt: "two pieces of a chest harness sitting on a messy workbench. both pieces are about 8 inches long total and consist of two large o-rings joined by a dark teal leather strap. the o rings and rivets are matte black."
@@ -1,5 +1,6 @@
---
title: domain and site setup
layout: post-with-toc.njk
image:
src: 2023/crinkly-mushrooms.jpg
alt: "Picture unrelated to post. Some crinkly brown-orange mushrooms in vibrant green grass."
+2 -1
View File
@@ -1,5 +1,6 @@
---
title: on pronouns
layout: post-with-toc.njk
image:
src: 2023/starling.jpg
alt: Image unrelated to post. A starling, a beautifully iridescent black bird, stands on a hanging suet feeder.
@@ -8,7 +9,7 @@ tags:
- gender
---
Created in cooperation with [Julia Pinedo](https://www.linkedin.com/in/julia-pinedo-094162117/).
Created in cooperation with [Jonah Pinedo](https://www.linkedin.com/in/jonahpinedo/).
Adapted from a workplace session on pronouns and gender identity.
@@ -1,5 +1,6 @@
---
title: gender as a proxy variable
layout: post-with-toc.njk
image:
src: 2024/gender-zine-cover.png
alt: "Part of a scan of the cover of my zine, Gender as a Proxy Variable. It shows the title and a bit of handsewn binding."
+1
View File
@@ -1,5 +1,6 @@
---
title: no politics (wip)
layout: post-with-toc.njk
image:
src: 2024/mushroom-on-fence.jpg
alt: "Picture unrelated to post. A small orange mushroom grows from the center of a fence post."
@@ -7,10 +7,6 @@ tags:
- reference
---
Updated 13 Aug 2024
The content previously found on this page is now hosted on a standalone site.
[Visit the site](https://rescue-trans-rescue.glitch.me).
(Site down? Not loading? [Check for issues with Glitch, our hosting provider](https://status.glitch.com/).)
[Visit rescue-trans-rescue.quest](https://rescue-trans-rescue.quest).
@@ -1,5 +1,6 @@
---
title: handedness toggle
layout: post-with-toc.njk
image:
src: 2024/handedness-toggle-0.png
alt: "A screenshot of the rescue trans rescue navbar centered on a button that shows a hand pointing left."
@@ -1,5 +1,6 @@
---
title: azure locations and file crawling
layout: post-with-toc.njk
image:
src: 2025/azure-locations.jpg
alt: "A Linux terminal. There is a fun rainbow flag in ascii art at the top, and then the user has called a command asking Azure for a list of locations applicable to a specific resource type. The output is lengthy."
+3 -2
View File
@@ -11,11 +11,12 @@ Listed by recency.
## 2026
- [Imbolc Celebration & Market at Beall Greenhouses](https://beall-greenhouses-market.pages.dev/events/2026-imbolc) (vendor, web marketing)
- [Beltane Market at Beall Greenhouses](https://beall-greenhouses.com/events/2027-beltane) (vendor, web marketing)
- [Imbolc Celebration & Market at Beall Greenhouses](https://beall-greenhouses.com/events/2026-imbolc) (vendor, web marketing)
## 2025
- [Solstice Market at Beall Greenhouses](https://beall-greenhouses-market.pages.dev/events/2025-solstice) (vendor, web and print marketing)
- [Solstice Market at Beall Greenhouses](https://beall-greenhouses.com/events/2025-solstice) (vendor, web and print marketing)
- [Seattle Zine Fest](https://www.instagram.com/seattle.zine.fest) (vendor)
- [VIVA Spring Tour](https://vivartists.com/viva/events/spring-tour-2025/) (vendor)
- [Seattle Erotic Art Festival](https://www.seaf.art) (displayed artist)
@@ -1,5 +1,6 @@
---
title: my favorite git flag
layout: post-with-toc.njk
image:
src: 2025/shelf-mushrooms.jpg
alt: "Picture unrelated to post. Creamy beige shelf mushrooms on a mossy tree trunk."
@@ -20,7 +21,7 @@ also, [TIL](https://xkcd.com/1053/): this command is a shortcut to the `patch` s
a classic scenario: you've realized your uncommitted work doesn't just encapsulate one change, and it's not so easily split as to be separable per-file. `git add -p` instead lets you choose to stage changes chunk-by-chunk, or, as `git` terms it, hunk-by-hunk.
### hunks
### hunks...
...are not perfect. you can split hunks, but only so much, and there's going to be cases where your changes are *so* mixed in as to be inseparable.
+1 -19
View File
@@ -1,5 +1,6 @@
---
title: siblinghood of the traveling greeting card
layout: post-with-toc.njk
image:
src: 2025/rockery.jpg
alt: "Image unrelated to post. A surprisingly neat pile of rounded beach rocks, mainly speckly grey-white-bluish ones, with trees in the background."
@@ -12,25 +13,6 @@ welcome to the siblinghood of the traveling greeting card. it now has a home at
originated on the fediverse - see the [#siblinghoodOfTheTravelingGreetingCard hashtag](https://flipping.rocks/tags/siblinghoodOfTheTravelingGreetingCard) - with original idea thanks to [noctiluca@scholar.social](https://scholar.social/@noctiluca)
## table of contents
- [objective](#objective)
- [outline](#outline)
- [timeline](#timeline)
- [participants](#participants)
- [on randomization](#on-randomization)
- [card guidelines](#card-guidelines)
- [address privacy](#address-privacy)
- [what I'll need from participants](#what-ill-need-from-participants)
- [signing the card](#signing-the-card)
- [mailing it back out](#mailing-it-back-out)
- [status checks](#status-checks)
- [what I'll send participants](#what-ill-send-participants)
- [guidelines](#guidelines)
- [recipient and loop order assignment](#recipient-and-loop-order-assignment)
- [reminders](#reminders)
- [I want in!](#i-want-in)
## objective
send a greeting card around the world. maybe more than one. we'll see.
+2 -1
View File
@@ -1,5 +1,6 @@
---
title: moving images
layout: post-with-toc.njk
image:
src: 2026/cormorant.jpg
alt: "Image unrelated to post. A cormorant, a type of black waterfowl, poses with wings spread on a buoy in Puget Sound. Off to the left, another bird floats."
@@ -10,7 +11,7 @@ tags:
## problem statement
today I decided to finally clean up the `assets/img` directory for this site. Since 2022, when I started this project, I've just been adding images directly to that directory with no further segmentation - messy of me, I know! It's gotten unwieldy and I'm starting to get worried about generic names leading to duplicates at some point, particularly for the non-gallery images where I have a tendency to [use](/stationery-exchange) [lots](/favorite-git-flag) [of](/trans-networks) [mushroom](/no-politics) [images](/domain-and-site-setup).
today I decided to finally clean up the `assets/img` directory for this site. Since 2022, when I started this project, I've just been adding images directly to that directory with no further segmentation - messy of me, I know! It's gotten unwieldy and I'm starting to get worried about generic names leading to duplicates at some point, particularly for the non-gallery posts where I have a tendency to [use](/stationery-exchange) [lots](/my-favorite-git-flag) [of](/networks-of-trans-care) [mushroom](/no-politics-wip) [images](/domain-and-site-setup).
so it's time to move them into year-based folders. Let's talk about how I did that. `bash` away!
+1 -48
View File
@@ -1,5 +1,6 @@
---
title: an intro to git
layout: post-with-toc.njk
image:
src: 2026/goldeneye-tail.jpg
alt: "Image unrelated to post. The tail of a diving duck pokes out from the water with a small splash."
@@ -10,54 +11,6 @@ tags:
alrighty, this one's a real doozy. Strap in.
---
<!-- TOC -->
- [versioning](#versioning)
- [problem statement](#problem-statement)
- [what is git?](#what-is-git)
- [where can I use git?](#where-can-i-use-git)
- [what is a CLI?](#what-is-a-cli)
- [where can I use the git CLI?](#where-can-i-use-the-git-cli)
- [git for Windows](#git-for-windows)
- [WSL](#wsl)
- [a few terminal operations](#a-few-terminal-operations)
- [edit files](#edit-files)
- [git version](#git-version)
- [a few handy settings](#a-few-handy-settings)
- [git going](#git-going)
- [git init](#git-init)
- [git clone](#git-clone)
- [git status](#git-status)
- [branch main](#branch-main)
- [no commits / nothing to commit](#no-commits--nothing-to-commit)
- [commits and history](#commits-and-history)
- [git log](#git-log)
- [creating a commit](#creating-a-commit)
- [the staging area](#the-staging-area)
- [git add](#git-add)
- [git commit](#git-commit)
- [checking our work](#checking-our-work)
- [changes to existing files](#changes-to-existing-files)
- [git restore](#git-restore)
- [git revert](#git-revert)
- [git remote](#git-remote)
- [git fetch and git pull](#git-fetch-and-git-pull)
- [git push, take one](#git-push-take-one)
- [authentication](#authentication)
- [SSH keys](#ssh-keys)
- [creation](#creation)
- [an alias...](#an-alias)
- [and a function](#and-a-function)
- [SSH keys and the remote](#ssh-keys-and-the-remote)
- [git push, take two](#git-push-take-two)
- [summary](#summary)
<!-- /TOC -->
---
## versioning
have you ever tried to revert to a previous version of a document in MS Office or Google Docs and found that your revision history is cluttered with small changes that by all rights should be grouped into one set of edits, but they aren't, and it's tedious to pick through all the versions?
@@ -1,5 +1,6 @@
---
title: comparing text editors
layout: post-with-toc.njk
image:
src: 2026/horsetail.jpg
alt: "Image unrelated to post. Close up on a horsetail plant's stem, with many small needle-like leaves emerging from all sides of the circular stem at each segmented joint."
@@ -1,5 +1,6 @@
---
title: screen reader optimizations
layout: post-with-toc.njk
image:
src: 2026/crow.jpg
alt: "Image unrelated to post. A crow poses on driftwood against a whitish sky."
@@ -1,5 +1,6 @@
---
title: eleventy lessons
layout: post-with-toc.njk
image:
src: 2026/hellebore.jpg
alt: Image unrelated to post. Close up on a pale green hellebore flower.
@@ -24,7 +25,7 @@ by default, the [Eleventy base blog](github.com/11ty/eleventy-base-blog) comes w
while that is useful for *this* site, when building another site I wanted to see a couple randomly-suggested posts that shared 1 or more tags.
I started by referring to [this GitHub issue about related posts](https://github.com/11ty/eleventy/discussions/2534){target="_blank rel="external"}. I had to fix a few errors that arose from the suggested code.
I started by referring to [this GitHub issue about related posts](https://github.com/11ty/eleventy/discussions/2534). I had to fix a few errors that arose from the suggested code.
I also wanted to make three changes:
@@ -1,5 +1,6 @@
---
title: accessible image modals
layout: post-with-toc.njk
image:
src: 2026/snacking-seagull.jpg
alt: Image unrelated to post. A seagull floating in the water with a starfish hanging out of eir mouth.
@@ -10,7 +11,7 @@ tags:
Recently I've been working on a single-page digital rendition of a zine complete with many hand-drawn images. The author wanted to be able to bring images up to a full-screen view, to either zoom in or to put the whole enlarged image on one screen with no scrolling. It was a real struggle to find resources on how to do this in an accessible manner, so I'm writing up what I did.
> Fair warning: This solution is likely imperfect.
> Fair warning: this solution is likely imperfect.
## the `dialog` element
+1
View File
@@ -1,5 +1,6 @@
---
title: core CSS
layout: post-with-toc.njk
image:
src: 2026/core-css.png
alt: "A website mockup in dark mode with light pink accents. Everything is filler text such as the title 'This is my cool website', headers reading things like 'This is an h1', nav items 'Nav item 1', etc. There is a paragraph block - the opening of the Bee Movie - and part of an image visible - a screencap of the music video for Never Gonna Give You Up by Rick Astley."
@@ -1,5 +1,6 @@
---
title: visual site builders and accessibility
layout: post-with-toc.njk
image:
src: 2026/roses.jpg
alt: Image unrelated to post. Two peach-colored roses, the farther away one a bit out of focus.
@@ -71,15 +72,17 @@ Want to just see the final ranking? Pop down to the [summary](#summary).
[Framer](https://framer.com) is a full-featured site designer with a built-in CMS. It offers generative AI features.
I have written [further thoughts on Framer accessibility](/framer-accessibility) as part of a more in-depth review.
| Factor | Notes | Score |
|---|---|---|
| Semantic HTML | Tags can be set per-element in the "Accessibility" section of the right-hand pane. Takes work, but is doable with care. | 2 |
| Keyboard navigation | Browser default focus outlines. Some weird clipping of focus outlines in the testing I did. Focus states configurable with custom CSS. | 2 |
| Keyboard navigation | Browser default focus outlines. Some weird clipping of focus outlines in the testing I did. Focus states configurable with custom CSS. Controls that require more than just the `tab` key suffer. | 1 |
| Reading order | With proper layout settings, reading order can be correct. Takes some effort and can't really just be stumbled into. | 2 |
| Text alternatives | Supported. | 3 |
| Color | Light and dark modes are possible. | 3 |
| Other | "Accessibility" section of the right-hand pane allows adding tab index. Defaults to 1 rather than 0. | 1 |
| | | **13** |
| | | **12** |
## Kiki
@@ -127,6 +130,20 @@ Want to just see the final ranking? Pop down to the [summary](#summary).
| Other | n/a | 2 |
| | | **10** |
## Squarespace
[Squarespace](https://www.squarespace.com/) is a visual site builder that starts you off with premade templates. It's somewhat block-based and limited in full customizability.
| Factor | Notes | Score |
|---|---|---|
| Semantic HTML | Template tested uses somewhat reasonable semantic HTML. Choice of what is considered a heading is a bit curious | 2 |
| Keyboard navigation | Template tested has custom tab focus styling. Cannot be further edited, but custom that fits the theme is pretty standout. Skip link included in at least some templates. | 3 |
| Reading order | Imperfect and can't be edited by user. Block-based layout is a little too freeform to ensure proper reading order, so the user should be careful where they add things. Early testing indicates that reading order is determined by the *first* place a block is placed, and is never re-assessed by the builder. | 1 |
| Text alternatives | Supported. | 3 |
| Color | Dark mode requires custom code or a plugin and seems *extremely* painful to accomplish. | 1 |
| Other | This isn't an accessibility consideration, but *christ* is Squarespace a pain to work with. | 1 |
| | | **11** |
## Startup
[Startup](https://designmodo.com/startup/) is a block-based builder with pre-defined components and less freedom than some others on this list.
@@ -223,9 +240,10 @@ Overall, I explored 11 builders, couldn't test 1 due to OS restrictions, and hav
|---|---|
| Webnode* | 14 |
| Figma Sites* | 13 |
| Framer* | 13 |
| Startup | 13 |
| Blocs** | 12 |
| Framer* | 12 |
| Squarespace* | 11 |
| Univer.se | 11 |
| Cowsites | 10 |
| Showit | 10 |
@@ -0,0 +1,137 @@
---
title: leatherworking zine
layout: post-with-toc.njk
image:
src: 2026/leatherworking-zine.jpg
alt: "3 copies of the same zine with different colored cardstock covers. The cover reads 'Leatherworking Tools' and lists myself as the author. Surrounding the text are many small icons of tools and explanatory diagrams. The text is dark teal and the icons are dark pink."
tags:
- gallery
- zine
- leather
draft: true
---
This page contains textual representation of and supplementary material for my Leatherworking Tools zine (purchase link to be added in the future), including links to all tools and additional information as needed.
## On tool links
Please note that links are examples, and you do not need the precise model linked. Where possible, I have found cheaper versions of tools - for example, you *can* get a fancy mallet or maul (they *are* nice), or you can get a 16oz or 32oz hardware store rubber mallet. I have linked the hardware store version.
Some things, like thread or rivets, come in other colors or finishes. Feel free to explore; I have linked only one.
## Retailers
Please note that I am familiar with US retailers, and cannot make recommendations for other countries.
My favorite leatherworking retailer is [Buckleguy](https://www.buckleguy.com/). They offer tools, hardware, leather, supplies, etc. and are generally extremely high quality with good customer service.
Occasionally, I will link other retailers such as [Tandy](https://tandyleather.com/) (a common retailer, but with products that may be lower quality - great for bulk leather for prototype and practice though!), [Weaver](https://www.weaverleathersupply.com/), or [Springfield](https://springfieldleather.com/). I will also link to non-leather specific retailers such as [Blick](https://www.dickblick.com/) and [Ace Hardware](https://www.acehardware.com/) as is relevant.
## Cover
The front and back cover spread is patterned with many small icons of leatherworking tools and explanatory diagrams in dark pink. Dark teal text reads "Leatherworking tools" "by Lee," and, on the back "2026."
## Page 1: Basics
- [Scratch awl](https://www.buckleguy.com/4-2-scratch-awl-3-1-2/) for marking
- Do not use a pen/sharpie/similar for marking as it will very much show on the finished product
- [Pattern plastic](https://www.weaverleathersupply.com/products/pattern-sheet-24-x-45) for templating
- [Leather thickness gauge](https://www.buckleguy.com/bg-acrylic-tool-leather-thickness-gauge/) for measuring
- You can also use calipers and a table of sizes, but this is very handy
## Page 2: Cut
- [Craft knife](https://www.dickblick.com/products/x-acto-1-knife/)
- Replace blades often
- [Non-slip metal ruler](https://www.dickblick.com/products/blick-aluminum-non-slip-rulers/)
- Metal is a must if you don't want to cut into your ruler
- [Cutproof mat](https://www.dickblick.com/products/blick-self-healing-cutting-mats/)
- [Strap end template](https://www.buckleguy.com/bg-acrylic-tool-belt-tabs-multiple-styles/)
If you're cutting a curve, make many straight cuts rather than one curved cut.
## Page 3: Burnish
### My core tools
- [Canvas](https://springfieldleather.com/products/burnishing-cloth-10-pk)
- Of course you can just go find some at a fabric store, but this lets you buy just a few small pieces
- [Tokonole](tandyleather.com/products/tokonole-burnishing-agent)
- You'll want clear Tokonole
- Shake before use
- You can apply this with a bit of cloth, [wool dauber](https://www.buckleguy.com/wool-daubers-5-length-12-per-bag/), [micro spatula](https://www.dickblick.com/products/lineco-micro-spatula/), etc... I just use my finger
### Other potential tools
- [Edge beveler](https://www.buckleguy.com/bg-leather-edge-beveler-multiple-sizes/)
- Proper finished edges should be beveled, but you can get away without this when starting
- [Sandpaper](https://www.acehardware.com/departments/paint-and-supplies/painting-tools-and-supplies/sandpaper/F035922?variationProductCode=19808)
- Grit varies; use significantly higher grits for final finish
- [Beeswax](https://www.buckleguy.com/fiebing-s-beeswax-1oz/)
## Page 4: Punch
- [Cutting board](https://www.buckleguy.com/cutting-board-multiple-sizes/)
- Don't use hole punches on your cutproof mat!
- [Mallet](https://www.acehardware.com/departments/tools/hand-tools/deadblow-hammers-mallets/2037238)
- Mauls are also an option
- [Single hole punches](https://www.buckleguy.com/245-belt-punch-multiple-sizes/), or...
- [Rotary punch](https://www.buckleguy.com/cs-osborne-223-revolving-punch/)
- If you choose a rotary punch, you don't need the cutting board and mallet (at least for this)
- I find rotary punches are too big for my small hands! So I prefer single hole punches
- [Oblong punches](https://www.buckleguy.com/cs-osborne-151-bag-punch-oblong-multiple-sizes/)
- If you're setting buckles, you might want this, or...
### Simulating an oblong punch
1. **Plan:** draw your oblong shape. You'll probably want it about as long as your leather strap is wide, and the width should be determined by the width of the buckle tongue
1. **Punch two holes:** punch a hole at each end of the oblong
1. **Cut from one side *halfway* in:** from one hole, cut halfway through the oblong
1. **Cut remainder of line from other side:** meet your existing cut
1. **Success!**
## Page 6: Stitch
- [Wing divider/scratch compass](https://www.buckleguy.com/bg-leather-wing-divider-compass-0-20mm/)
- Lets you draw guidelines an even distance from edges
- Craft store compasses *may* work, but you'd want to ensure that they are pointed enough to mark a line
- [Stitching chisels](https://www.buckleguy.com/bg-stitching-punch/)
- Get a 2-tooth and one with lots of teeth - a full set is nice, but not as necessary
- Also called "pricking irons"
- **Use these with your cutting board, *not* your cutproof mat**
- You can also use a combination of a [marking wheel](https://www.buckleguy.com/japanese-stitching-marking-wheel-curved-handle/) and [awl](https://www.buckleguy.com/bg-leather-awls-detachable-needle/), but this *will* be slower and you won't be able to punch out 6-9 stitches at once
- 2 [Blunt tip needles](https://www.buckleguy.com/517-harness-needles-for-hand-sewing-blunt-tip-5-needles/)
- [Waxed polyester thread](https://www.buckleguy.com/ritza-25-tiger-thread-waxed-polyester-cream/)
- I use 0.8mm thickness
- Lighter (you don't need a link
### Saddle stitch
I recommend watching [How to Saddle Stitch](https://www.youtube.com/watch?v=nHL_duaJxWQ) in addition to reading my single-page overview. Particularly useful is his method of securing the thread to the needle (I just didn't have the space to cover this).
1. Pre-punch holes
1. Thread needles on both ends
1. Thread through first hole
1. Needle 1 through next hole
1. Follow with needle 2. Pull existing thread to the side to avoid piercing it
1. Pull tight with even tension
1. Repeat
To finish, stitch backwards for a few stitches. Trim ends short. Melt. Flatten by rubbing against metal end of lighter.
## Page 8: Rivet
One end of the rivet sits in the bowl of the **anvil**. The other end caps on and is nested in the **setter**, which is then hit with a mallet (or maul).
A basic setter and anvil has an anvil that is larger than the rivet.
- **Good:** works with multiple rivet sizes; cheap and common
- **Bad:** hard to set evenly
My preference is a fixed-size setter and anvil. The anvil is sized to the rivet cap size.
- **Good:** better looking and easier
- **Bad:** only one size of rivet; often higher quality which raises the price
- [Basic double-cap rivets, setter, and anvil set](https://tandyleather.com/products/easy-to-do-rivets-setter)
- Fixed-size [setter](https://www.buckleguy.com/bg-rivet-setter-concave-end-multiple-sizes/) and [anvil](https://www.buckleguy.com/bg-rivet-setter-base-for-9-2-11-13mm-cap-rivets/); paired [double-cap rivets](https://www.buckleguy.com/double-cap-rivet-antique-brass-solid-brass-ll-100-sets-per-bag-multiple-sizes/)
@@ -1,5 +1,6 @@
---
title: framer accessibility
layout: post-with-toc.njk
image:
src: 2026/framer.png
alt: "A screenshot of the Framer projects page showing part of the tile for a very rudimentary project titled Accessibility Test. It has a huge title that just reads Title, a basic form, and some pictures of my dog as notable features."
@@ -23,7 +24,7 @@ Accessibility **must** be built from the start of a project. Retrofitting a proj
## Semantic HTML
Most HTML elements are semantic, that is, they convey meaning. Labeling something an `<h1>` doesn't just style it like a header; it also means that assistive tech can understand it to be a header (this also helps with SEO - a lot of things that improve accessibility improve SEO as well). See the Mozilla docs for a [list of semantic HTML elements](https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantic_elements).
Most HTML elements are semantic, that is, they convey meaning. Labeling something an `<h1>` doesn't just style it like a header; it also means that AT can understand it to be a header (this also helps with SEO - a lot of things that improve accessibility improve SEO as well). See the Mozilla docs for a [list of semantic HTML elements](https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantic_elements).
Notably, `<div>`s and `<span>`s are not semantic and convey no meaning. They are used for styling alone.
@@ -31,6 +32,8 @@ Notably, `<div>`s and `<span>`s are not semantic and convey no meaning. They are
Semantic HTML elements can be applied to any Framer element using the "Accessibility" section in the right-hand sidebar. Read about [using semantic tags for navigation and footers](https://www.framer.com/help/articles/semantic-tags-navigation-footer/) - this applies to far more than the two elements mentioned.
While Framer allows you to set the `<span>` tag on elements, avoid this unless you are *only* utilizing it for styling.
## Reading order
The order of elements in an HTML document is referred to as the **reading order**. While visual styling can change the flow of elements in a page, SRs will follow reading order. It's important for your reading order to match the visual flow of elements on the page for two reasons:
@@ -60,6 +63,8 @@ Links, buttons, and form controls are tabbable by default. When tagged as the co
[Framer supports adding the tabindex attribute](https://www.framer.com/help/articles/tab-order-customization/). If you *must* do this for some reason, make sure to set its value to 0 - Framer defaults to 1. 0 will maintain the reading order established by layout and the left-hand sidebar; 1 will place the tabbable element first in the tabbing order.
I really recommend avoiding complex keyboard navigation like dropdowns (really not that complex, but... basically anything that doesn't just use the tab key suffers). They seem pretty impossible to remediate. If possible, it requires *extensive* custom code.
## Keyboard focus
When navigating with a keyboard, there should always be visual indication on the screen of where we have navigated to. This indication is referred to as **focus** or the **focus indicator**. Browsers have default focus stylings, usually an outline around the element, but focus can - and frequently should - be customized with CSS. Default focus outlines may not have very high contrast against the elements in your website, and, unless you are testing with many browsers, you can't easily confirm that all default focus indication works well with your color scheme. Additionally, default focus may clash with your site and impact how elements like your forms look in use.
@@ -68,7 +73,7 @@ When navigating with a keyboard, there should always be visual indication on the
Framer does not currently allow for customizing keyboard focus in the editor. It must be done using [custom CSS](https://www.framer.com/help/articles/how-to-add-custom-code/).
In my tests, it was possible to clip out the browser default focus outline with certain padding settings. Review your site by tabbing through the page(s), and ensure that a full outline surrounds all interactable elements. If an outline is missing, consider adjusting the padding around that element.
In my tests, it was very possible to clip out the browser default focus outline with certain padding settings. Ensure that at least 3px of padding surrounds tabbable elements. Make sure to review your site by tabbing through the page(s), and ensure that a full outline surrounds all interactable elements.
## Skip links
@@ -120,9 +125,9 @@ Accessible forms can be *hard*. They bring in challenges relating to labeling, v
### Forms in Framer
1. **Labeling:** follow the pattern that Framer uses in its basic form for labeling. This will nest the form control inside the label.
- If you want an invisible label, you will need to write custom CSS.
- If you want an invisible label, you will need to write custom CSS.
1. **Validation:** In the "Input" section of the right-hand sidebar, there is a dropdown for input type. There is also a toggle for whether the input is required.
- Note that setting an input to required will not add an asterisk or any other similar visual pattern to the label - doing this yourself is highly recommended. It also will not provide visual feedback to the user until clicking the "Submit" button, at which point an error message comes up - this can be a painful pattern for longer forms. Further visual feedback requires custom CSS.
- Note that setting an input to required will not add an asterisk or any other similar visual pattern to the label - doing this yourself is highly recommended. It also will not provide visual feedback to the user until clicking the "Submit" button, at which point an error message comes up - this can be a painful pattern for longer forms. Further visual feedback requires custom CSS.
1. **Reading order:** follow the guidance for reading order discussed earlier.
1. **Color:** since visual feedback for required feeds does not exist by default, this only becomes a concern if you write custom CSS.