Compare commits
231
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
230e86bf7c | ||
|
|
32b055f328 | ||
|
|
438d1a67e2 | ||
|
|
cd7f525bac | ||
|
|
6933f11630 | ||
|
|
62dab04ee9 | ||
|
|
e60d191e09 | ||
|
|
efe79ff639 | ||
|
|
4be20cccb3 | ||
|
|
aba74f280e | ||
|
|
0125216d96 | ||
|
|
6ee81d8784 | ||
|
|
2bfe616195 | ||
|
|
f9d8123b9d | ||
|
|
c7ef4c701a | ||
|
|
d8f3ea3430 | ||
|
|
a9b96e567e | ||
|
|
bc1a51a4d5 | ||
|
|
16c3ef1e26 | ||
|
|
efe153191a | ||
|
|
8c2c2231ac | ||
|
|
62b1e448ea | ||
|
|
d53198e1aa | ||
|
|
c6ec6b8f48 | ||
|
|
75909355ba | ||
|
|
d5660455bd | ||
|
|
7df4c1ff8e | ||
|
|
d6c2bb9aa9 | ||
|
|
604a6787f4 | ||
|
|
980cd0b3a6 | ||
|
|
5be42a4ff3 | ||
|
|
25c8e56a76 | ||
|
|
8752eeb904 | ||
|
|
b1135beddb | ||
|
|
84160a0574 | ||
|
|
557308f3f9 | ||
|
|
382419e6d6 | ||
|
|
66df77c32c | ||
|
|
a3e0ba5037 | ||
|
|
51d836c71b | ||
|
|
67e70e68ab | ||
|
|
b31e683786 | ||
|
|
1bb26176ba | ||
|
|
a000d1c1b9 | ||
|
|
cf26b06e3d | ||
|
|
5acda53f58 | ||
|
|
f2bc045735 | ||
|
|
3b1c5ffa88 | ||
|
|
0882fcda41 | ||
|
|
7d042abe1d | ||
|
|
f5bbda1f14 | ||
|
|
9999775e44 | ||
|
|
463cabe793 | ||
|
|
4aa7516cb9 | ||
|
|
f49a7faa4d | ||
|
|
2e26cefab2 | ||
|
|
870a6e5e0f | ||
|
|
be364d7644 | ||
|
|
06bcfc1522 | ||
|
|
dd1943bcdd | ||
|
|
bfa91ea19f | ||
|
|
b4fbeffc41 | ||
|
|
25cf8a38ec | ||
|
|
5724f509a0 | ||
|
|
fe6956aaa3 | ||
|
|
846ef7538f | ||
|
|
f8aacdc85d | ||
|
|
776218805a | ||
|
|
91c7f14113 | ||
|
|
8bcdaeff52 | ||
|
|
3e766eb519 | ||
|
|
2ad41daa2e | ||
|
|
7b248c24b9 | ||
|
|
abec70c655 | ||
|
|
2d35768db9 | ||
|
|
30498307c8 | ||
|
|
953f651c4f | ||
|
|
ee0a39333d | ||
|
|
a2fd1cb797 | ||
|
|
9889cf4adb | ||
|
|
a3b9d20dfb | ||
|
|
1a0898c214 | ||
|
|
07bb31111f | ||
|
|
c517bb8d69 | ||
|
|
830c1a4666 | ||
|
|
1a2850ca8c | ||
|
|
96e70dbd2f | ||
|
|
58da634ec7 | ||
|
|
d8049a1f34 | ||
|
|
12ae5f9a4e | ||
|
|
672a03d4e9 | ||
|
|
0e46e65034 | ||
|
|
782912c8a6 | ||
|
|
470a84429c | ||
|
|
05e40f0ea7 | ||
|
|
35841f26fd | ||
|
|
3fc4468d09 | ||
|
|
bbcdb5ee03 | ||
|
|
d663b851c9 | ||
|
|
4ac0441c3d | ||
|
|
f6620e19a4 | ||
|
|
df9b5e4c55 | ||
|
|
f4a32e5292 | ||
|
|
01c0bf00a2 | ||
|
|
ff03344b81 | ||
|
|
e437febdf8 | ||
|
|
21858e5dd3 | ||
|
|
a780e7cc9e | ||
|
|
d0cb1cf7f5 | ||
|
|
cd30f192eb | ||
|
|
d246ba3437 | ||
|
|
7abb27739e | ||
|
|
742d2b9666 | ||
|
|
3ff187ae10 | ||
|
|
0ec803b447 | ||
|
|
1863efa802 | ||
|
|
153a90fb0a | ||
|
|
0a5d393618 | ||
|
|
532424c953 | ||
|
|
9b5ee21bf7 | ||
|
|
33ad5815a7 | ||
|
|
7a30ee3216 | ||
|
|
88562bd766 | ||
|
|
75d3a12bdc | ||
|
|
f488a6aa54 | ||
|
|
8c135a09c7 | ||
|
|
7ede08fd43 | ||
|
|
e80f340642 | ||
|
|
4b43f76ac4 | ||
|
|
54b63df970 | ||
|
|
b40f41a5f7 | ||
|
|
1cf7b8560e | ||
|
|
ba5b01d084 | ||
|
|
feaaeb30b7 | ||
|
|
4af8d68ac9 | ||
|
|
c51e5b502a | ||
|
|
6585b8e74d | ||
|
|
22d4c48b46 | ||
|
|
18989f817f | ||
|
|
5dfaac6820 | ||
|
|
814d4efe8b | ||
|
|
0b0822d21b | ||
|
|
f1c073535d | ||
|
|
4f0a0f3969 | ||
|
|
c4b7faca88 | ||
|
|
68487ad342 | ||
|
|
2b90da7572 | ||
|
|
58be723eef | ||
|
|
72c5904c27 | ||
|
|
e615e6a91f | ||
|
|
a56ca4c03e | ||
|
|
9a483ad27c | ||
|
|
63e225aebc | ||
|
|
60c07e629b | ||
|
|
ff1fa0a966 | ||
|
|
64007ea884 | ||
|
|
1108f38939 | ||
|
|
cddc20ad3d | ||
|
|
3a9095c4e8 | ||
|
|
914243feb9 | ||
|
|
3f9e6727de | ||
|
|
f980c8c682 | ||
|
|
8104cd4520 | ||
|
|
4f38bbfc82 | ||
|
|
56736453fe | ||
|
|
c04993c983 | ||
|
|
ed3a845a55 | ||
|
|
c8ce389065 | ||
|
|
c95b3c080a | ||
|
|
c559aa9154 | ||
|
|
a14753e656 | ||
|
|
82db8f8758 | ||
|
|
d434da450f | ||
|
|
913f8469f3 | ||
|
|
4f12d9c5ac | ||
|
|
e14261bf4d | ||
|
|
073ad660e4 | ||
|
|
c6dcdacbec | ||
|
|
8ab1cb687b | ||
|
|
ac1903c5a1 | ||
|
|
bf677c3cdf | ||
|
|
8adb83d8a8 | ||
|
|
0439f0478d | ||
|
|
ebe2490fd3 | ||
|
|
409ca37f74 | ||
|
|
e129b26e63 | ||
|
|
dc49b1cad5 | ||
|
|
21e3dca187 | ||
|
|
ff9eb09838 | ||
|
|
ce6aa0fb00 | ||
|
|
f89f135f9b | ||
|
|
422a0e45e8 | ||
|
|
191ee1a355 | ||
|
|
43ccb40e0b | ||
|
|
b5aff7207e | ||
|
|
aa9951e68d | ||
|
|
35519d9d4b | ||
|
|
43ae5c489e | ||
|
|
b51e953a1b | ||
|
|
0e14d3ca72 | ||
|
|
50d4b61037 | ||
|
|
73a0278392 | ||
|
|
b241cc14af | ||
|
|
98c00bb1fd | ||
|
|
bfefa33f13 | ||
|
|
89ff36afc7 | ||
|
|
afbf693d3b | ||
|
|
a3ba14abd2 | ||
|
|
e45e9b0f7a | ||
|
|
3e61e004f4 | ||
|
|
58a412f002 | ||
|
|
64db3a2446 | ||
|
|
a03a1b6c52 | ||
|
|
7f5dc28cad | ||
|
|
7e95d9ff16 | ||
|
|
6e3bfd9a08 | ||
|
|
ae056c75bd | ||
|
|
5c786b15d2 | ||
|
|
2c3711fe1e | ||
|
|
f18e2f2078 | ||
|
|
9a566f99ab | ||
|
|
9db3d3b34c | ||
|
|
9249a6e050 | ||
|
|
7d1fe776c7 | ||
|
|
c4b549bc75 | ||
|
|
6203735ff8 | ||
|
|
3848af101b | ||
|
|
25f5d5897b | ||
|
|
fc71c05327 | ||
|
|
d080981f2d | ||
|
|
778d323db9 |
No files matched your search
+28
@@ -0,0 +1,28 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: node:current
|
||||||
|
environment:
|
||||||
|
REPOSITORY: leecat.art-site
|
||||||
|
GIT_USER: inherentlee
|
||||||
|
GIT_TOKEN:
|
||||||
|
from_secret: GIT_TOKEN
|
||||||
|
commands:
|
||||||
|
- git config credential.helper '!f() { echo username=$GIT_USER; echo "password=$GIT_TOKEN"; };f'
|
||||||
|
- git submodule update --remote --init --merge
|
||||||
|
- npm install
|
||||||
|
- npm run build
|
||||||
|
- apt-get update && apt-get install -y rsync
|
||||||
|
- rsync -uavh _site/ $REPOSITORY --delete --exclude .git
|
||||||
|
- cd $REPOSITORY
|
||||||
|
- git checkout main
|
||||||
|
- git config --global --add safe.directory /drone/src/$REPOSITORY
|
||||||
|
- git add -A
|
||||||
|
- git commit -m "drone build $(TZ=':America/Los_Angeles' date)"
|
||||||
|
- git push
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
# npm
|
# npm
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
# build
|
||||||
|
_site
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "leecat.art-site"]
|
||||||
|
path = leecat.art-site
|
||||||
|
url = https://heckin.technology/inherentlee/leecat.art-site.git
|
||||||
@@ -2,4 +2,22 @@
|
|||||||
|
|
||||||
Lee Cattarin's personal website, v2. Built on Eleventy.
|
Lee Cattarin's personal website, v2. Built on Eleventy.
|
||||||
|
|
||||||
Not live yet.
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm i
|
||||||
|
# or
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run locally
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build website
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
+70
-12
@@ -1,34 +1,92 @@
|
|||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
export default function(eleventyConfig) {
|
export default function (eleventyConfig) {
|
||||||
// Return the keys used in an object
|
// Return the keys used in an object
|
||||||
eleventyConfig.addFilter("getKeys", target => {
|
eleventyConfig.addFilter("getKeys", (target) => {
|
||||||
return Object.keys(target);
|
return Object.keys(target);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* Exclude all posts with given URLs from a collection list */
|
||||||
|
eleventyConfig.addFilter(
|
||||||
|
"excludeFromCollection",
|
||||||
|
function (collection = [], urls = [this.ctx.page.url]) {
|
||||||
|
return collection.filter((post) => urls.indexOf(post.url) === -1);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Filter a collection by a set of tags, returning any that share one or more tags */
|
||||||
|
eleventyConfig.addFilter(
|
||||||
|
"filterByTags",
|
||||||
|
function (collection = [], ...requiredTags) {
|
||||||
|
return collection.filter((post) => {
|
||||||
|
return requiredTags.flat().some((tag) => post.data.tags.includes(tag));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Return n elements from a list */
|
||||||
|
eleventyConfig.addFilter("head", (collection = [], n) => {
|
||||||
|
if (!Array.isArray(collection) || collection.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (n < 0) {
|
||||||
|
return collection.slice(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return collection.slice(0, n);
|
||||||
|
});
|
||||||
|
|
||||||
/* For <time> elements */
|
/* For <time> elements */
|
||||||
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
|
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
|
||||||
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat('yyyy-LL-dd');
|
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat("yyyy-LL-dd");
|
||||||
|
});
|
||||||
|
|
||||||
|
/* What it says on the tin */
|
||||||
|
eleventyConfig.addFilter("randomize", function (array) {
|
||||||
|
// Create a copy of the array to avoid modifying the original
|
||||||
|
let shuffledArray = array.slice();
|
||||||
|
|
||||||
|
// Fisher-Yates shuffle algorithm
|
||||||
|
for (let i = shuffledArray.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[shuffledArray[i], shuffledArray[j]] = [
|
||||||
|
shuffledArray[j],
|
||||||
|
shuffledArray[i],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return shuffledArray;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Human-readable dates */
|
/* Human-readable dates */
|
||||||
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
|
eleventyConfig.addFilter("readableDate", (dateObj) => {
|
||||||
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" })
|
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toLocaleString(
|
||||||
.toLocaleString(DateTime.DATE_FULL);
|
DateTime.DATE_FULL,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Filter out structural tags */
|
/* Filter out structural tags */
|
||||||
eleventyConfig.addFilter("removeBasicTags", (tags) => {
|
eleventyConfig.addFilter("removeBasicTags", (tags) => {
|
||||||
return tags.filter(tag => ["all", "posts", "gallery", "reference", "tagPagination"].indexOf(tag) === -1);
|
return tags.filter(
|
||||||
|
(tag) =>
|
||||||
|
[
|
||||||
|
"all",
|
||||||
|
"posts",
|
||||||
|
"gallery",
|
||||||
|
"reference",
|
||||||
|
"tagPagination",
|
||||||
|
"blur",
|
||||||
|
].indexOf(tag) === -1,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* What it says */
|
/* What it says on the tin */
|
||||||
eleventyConfig.addFilter("sortAlphabetically", strings =>
|
eleventyConfig.addFilter("sortAlphabetically", (strings) =>
|
||||||
(strings || []).sort((b, a) => b.localeCompare(a))
|
(strings || []).sort((b, a) => b.localeCompare(a)),
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Remove year from image filenames for OG metadata */
|
/* Remove year from image filenames for OG metadata file path */
|
||||||
eleventyConfig.addFilter("toOgFilename", (filename) => {
|
eleventyConfig.addFilter("toOgFilename", (filename) => {
|
||||||
return filename.split("/")[1];
|
return filename.split("/")[1];
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
+24
-3
@@ -1,7 +1,7 @@
|
|||||||
<footer>
|
<footer>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="/colophon" title="colophon" aria-label="colophon"
|
<a href="/colophon/"
|
||||||
{% if page.url == "/colophon/" %}aria-current="page"{% endif %}>
|
{% if page.url == "/colophon/" %}aria-current="page"{% endif %}>
|
||||||
colophon
|
colophon
|
||||||
</a>
|
</a>
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/" title="go home"
|
<a href="/" title="go home"
|
||||||
aria-label="go home | {{ metadata.title }} from {{ metadata.author }} in 2026"
|
aria-label="go home | {{ metadata.title }} from {{ metadata.author }}, copyright 2022-2026"
|
||||||
{% if page.url == "/" %}aria-current="page"{% endif %}>
|
{% if page.url == "/" %}aria-current="page"{% endif %}>
|
||||||
{{ metadata.title }} from {{ metadata.author }} in 2026</a>
|
{{ metadata.title }} from {{ metadata.author }}, © 2022-2026</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
@@ -21,4 +21,25 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<fieldset id="theme">
|
||||||
|
<legend>color scheme</legend>
|
||||||
|
|
||||||
|
<input type="radio" id="theme-light" name="theme" value="light"/>
|
||||||
|
<label class="theme-light" for="theme-light">
|
||||||
|
<i class="fa-regular fa-sun" aria-hidden="true"></i>
|
||||||
|
light
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="radio" id="theme-auto" name="theme" value="auto" checked/>
|
||||||
|
<label class="theme-auto" for="theme-auto">
|
||||||
|
auto
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="radio" id="theme-dark" name="theme" value="dark"/>
|
||||||
|
<label class="theme-dark" for="theme-dark">
|
||||||
|
dark
|
||||||
|
<i class="fa-regular fa-moon" aria-hidden="true"></i>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||||
|
|
||||||
|
{% set pageTitle %}{{ title | safe }} | {{ metadata.title }}{% endset %}
|
||||||
|
<title>{{ pageTitle }}</title>
|
||||||
|
<meta name="description" content="{{ description or metadata.description }}">
|
||||||
|
<link rel="alternate" href="/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
|
||||||
|
|
||||||
|
<meta property="og:title" content="{{ pageTitle }}" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:description" content="{{ description or metadata.description }}" />
|
||||||
|
<meta property="og:site_name" content="{{ metadata.title }}" />
|
||||||
|
<meta property="og:url" content="{{ metadata.url }}{{ page.url }}" />
|
||||||
|
{% if image %}
|
||||||
|
<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 }}">
|
||||||
|
|
||||||
|
<meta itemprop="ai-content-declaration:version" content="1.0.0">
|
||||||
|
<meta itemprop="ai-content-declaration:level" content="none">
|
||||||
|
|
||||||
|
{# Fonts #}
|
||||||
|
<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=Atkinson+Hyperlegible+Mono:ital,wght@0,200..800;1,200..800&family=Atkinson+Hyperlegible+Next:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
{# Icons #}
|
||||||
|
<script src="https://kit.fontawesome.com/884dded219.js" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
{# Styles #}
|
||||||
|
<style>{% include "css/main.css" %}</style>
|
||||||
|
<style>{% include "css/nav.css" %}</style>
|
||||||
|
<style>{% include "css/pagefind.css" %}</style>
|
||||||
|
<style>{% include "css/highlighting.css" %}</style>
|
||||||
|
<style>{% include "css/print.css" %}</style>
|
||||||
|
|
||||||
|
<style>{% getBundle "css" %}</style>
|
||||||
|
|
||||||
|
{# Scripts #}
|
||||||
|
<script>{% include "js/theme.js" %}</script>
|
||||||
|
<script type="module">{% getBundle "js" %}</script>
|
||||||
|
|
||||||
|
{# Pagefind #}
|
||||||
|
<link href="/pagefind/pagefind-component-ui.css" rel="stylesheet">
|
||||||
|
<script src="/pagefind/pagefind-component-ui.js" type="module"></script>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<header>
|
<header>
|
||||||
|
<a href="#main" id="skip" title="skip to main content">
|
||||||
<a href="#main" id="skip" title="skip to main content" aria-label="skip to main content">
|
|
||||||
<i class="fa-solid fa-forward" aria-hidden="true"></i> skip
|
<i class="fa-solid fa-forward" aria-hidden="true"></i> skip
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -9,8 +8,7 @@
|
|||||||
{% for entry in collections.all | eleventyNavigation %}
|
{% for entry in collections.all | eleventyNavigation %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ entry.url }}" title="{{ entry.data.label }}"
|
<a href="{{ entry.url }}" title="{{ entry.data.label }}"
|
||||||
{% if entry.url == page.url %}aria-current="page"{% endif %}
|
{% if entry.url == page.url %}aria-current="page"{% endif %}>
|
||||||
aria-label="{{ entry.data.label }}">
|
|
||||||
<i class="{{ entry.data.icon }}" aria-hidden="true"></i>
|
<i class="{{ entry.data.icon }}" aria-hidden="true"></i>
|
||||||
<span class="menu-text">{{ entry.title }}</span>
|
<span class="menu-text">{{ entry.title }}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -19,4 +17,10 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<div class="dark searchbox" data-pf-theme="dark">
|
||||||
|
<pagefind-searchbox></pagefind-searchbox>
|
||||||
|
</div>
|
||||||
|
<div class="light searchbox">
|
||||||
|
<pagefind-searchbox></pagefind-searchbox>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
+13
-47
@@ -1,51 +1,17 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<head>
|
<html lang="en">
|
||||||
<meta charset="utf-8">
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% include "head-content.njk" %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% include "header.njk" %}
|
||||||
|
|
||||||
{% set pageTitle %}{{ title }} | {{ metadata.title }}{% endset %}
|
<main id="main">
|
||||||
<title>{{ pageTitle }}</title>
|
{{ content | safe }}
|
||||||
<meta name="description" content="{{ description or metadata.description }}">
|
</main>
|
||||||
<link rel="alternate" href="/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
|
|
||||||
|
|
||||||
<meta property="og:title" content="{{ title or metadata.title }}" />
|
{% include "footer.njk" %}
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:description" content="{{ description or metadata.description }}" />
|
|
||||||
<meta property="og:site_name" content="{{ metadata.title }}" />
|
|
||||||
{% if image %}
|
|
||||||
<meta property="og:image" content="/img/{{ image.src | toOgFilename }}" />
|
|
||||||
<meta property="og:image:alt" content="{{ image.alt }}" />
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<meta name="generator" content="{{ eleventy.generator }}">
|
<!-- This page `{{ page.url }}` was built on {% currentBuildDate %} -->
|
||||||
|
</body>
|
||||||
{# Fonts #}
|
</html>
|
||||||
<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=Atkinson+Hyperlegible+Mono:ital,wght@0,200..800;1,200..800&family=Atkinson+Hyperlegible+Next:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
{# Icons #}
|
|
||||||
<script src="https://kit.fontawesome.com/884dded219.js" crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
{# Styles #}
|
|
||||||
<style>{% include "css/main.css" %}</style>
|
|
||||||
<style>{% include "css/nav.css" %}</style>
|
|
||||||
<style>{% include "css/print.css" %}</style>
|
|
||||||
|
|
||||||
<style>{% getBundle "css" %}</style>
|
|
||||||
|
|
||||||
<script type="module">{% getBundle "js" %}</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% include "header.njk" %}
|
|
||||||
|
|
||||||
<main id="main">
|
|
||||||
{{ content | safe }}
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
{% include "footer.njk" %}
|
|
||||||
|
|
||||||
<!-- This page `{{ page.url }}` was built on {% currentBuildDate %} -->
|
|
||||||
<body>
|
|
||||||
@@ -3,7 +3,7 @@ layout: base.njk
|
|||||||
---
|
---
|
||||||
{% js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
|
{% js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
|
||||||
|
|
||||||
<heading-anchors content="<i class='fa-solid fa-anchor'></i>">
|
<heading-anchors content="<i class='fa-solid fa-anchor'></i>" data-pagefind-body>
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
|
|||||||
@@ -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 }}
|
||||||
@@ -2,11 +2,13 @@
|
|||||||
layout: base.njk
|
layout: base.njk
|
||||||
---
|
---
|
||||||
{% css %}{% include "css/post.css" %}{% endcss %}
|
{% css %}{% include "css/post.css" %}{% endcss %}
|
||||||
{% css %}{% include "css/highlighting.css" %}{% endcss %}
|
{% css %}{% include "css/lists.css" %}{% endcss %}
|
||||||
|
{% css %}{% include "css/modal.css" %}{% endcss %}
|
||||||
{% js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
|
{% js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
|
||||||
|
{% js %}{% include "js/modal.js" %}{% endjs %}
|
||||||
|
|
||||||
<heading-anchors content="<i class='fa-solid fa-anchor'></i>">
|
<heading-anchors content="<i class='fa-solid fa-anchor'></i>">
|
||||||
<article>
|
<article data-pagefind-body>
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
<div class="post-metadata">
|
<div class="post-metadata">
|
||||||
@@ -29,7 +31,11 @@ layout: base.njk
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if image %}
|
{% if image %}
|
||||||
<img src="/img/{{ image.src }}" alt="{{ image.alt }}">
|
<dialog closedby="any" aria-label="image modal" tabindex="-1">
|
||||||
|
<button class="close-dialog" autofocus aria-label="close the image modal">×</button>
|
||||||
|
<img class="modal-img" src="/img/{{ image.src }}" alt="{{ image.alt }}">
|
||||||
|
</dialog>
|
||||||
|
<img class="hero" src="/img/{{ image.src }}" alt="{{ image.alt }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
@@ -43,4 +49,16 @@ layout: base.njk
|
|||||||
{% set newerTitle = newerPost.data.title %}
|
{% set newerTitle = newerPost.data.title %}
|
||||||
{% set inPost = true %}
|
{% set inPost = true %}
|
||||||
{% include "pagination.njk" %}
|
{% include "pagination.njk" %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{% set relevantTags = tags | removeBasicTags %}
|
||||||
|
{% set postlist = collections.posts | filterByTags(relevantTags) | excludeFromCollection([page.url, olderHref, newerHref]) | randomize | head(3) %}
|
||||||
|
{% if postlist.length %}
|
||||||
|
<section class="related-posts">
|
||||||
|
<h2 data-ha-exclude>related posts</h2>
|
||||||
|
{% include "postlist.njk" %}
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</heading-anchors>
|
</heading-anchors>
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
layout: base.njk
|
|
||||||
---
|
|
||||||
{% css %}{% include "css/resume.css" %}{% endcss %}
|
|
||||||
|
|
||||||
{{ content | safe }}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
{% include "head-content.njk" %}
|
||||||
|
|
||||||
|
<meta http-equiv="refresh" content="0; url=/tags/{{ tag }}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% include "header.njk" %}
|
||||||
|
|
||||||
|
<main id="main">
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
|
{{ content | safe }}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{% include "footer.njk" %}
|
||||||
|
|
||||||
|
<!-- This page `{{ page.url }}` was built on {% currentBuildDate %} -->
|
||||||
|
<body>
|
||||||
|
</html>
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
<ol id="postlist">
|
<ol id="postlist">
|
||||||
{% for post in postlist %}
|
{% for post in postlist %}
|
||||||
<li class="post">
|
<li class="post">
|
||||||
<a class="postlink" href="{{ post.url }}">
|
<a class="postlink" href="{{ post.url }}">
|
||||||
|
<h2 data-ha-exclude>{{ post.data.title }} {% if "blur" in post.data.tags %}(mature){% endif %}</h2>
|
||||||
{% if post.data.image %}
|
{% if post.data.image %}
|
||||||
<img src="/img/{{ post.data.image.src }}" alt="{{ post.data.image.alt }}">
|
|
||||||
{% endif %}
|
|
||||||
<h2>{{ post.data.title }}</h2>
|
|
||||||
<ul class="postlist-tags">
|
<ul class="postlist-tags">
|
||||||
{% for tag in post.data.tags | removeBasicTags %}
|
{% for tag in post.data.tags | removeBasicTags %}
|
||||||
<li>{{ tag }}</li>
|
<li>{{ tag }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
<img src="/img/{{ post.data.image.src }}" alt="{{ post.data.image.alt }}"
|
||||||
|
{% if "blur" in post.data.tags %}class="blur"{% endif %}>
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
-144
@@ -1,144 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
|
|
||||||
<title>hello hello</title>
|
|
||||||
<subtitle>Lee Cattarin... on the internet!</subtitle>
|
|
||||||
<link href="https://leecat.art/feed.xml" rel="self" />
|
|
||||||
<link href="https://leecat.art/" />
|
|
||||||
<updated>2026-02-19T21:09:51Z</updated>
|
|
||||||
<id>https://leecat.art/</id>
|
|
||||||
<author>
|
|
||||||
<name>Lee Cattarin</name>
|
|
||||||
<email>lee.cattarin@gmail.com</email>
|
|
||||||
</author>
|
|
||||||
<entry>
|
|
||||||
<title>screen reader optimizations</title>
|
|
||||||
<link href="https://leecat.art/screen-reader-optimizations/" />
|
|
||||||
<updated>2026-02-19T21:09:51Z</updated>
|
|
||||||
<id>https://leecat.art/screen-reader-optimizations/</id>
|
|
||||||
<content type="html"><h2 id="context">context</h2>
|
|
||||||
<p>recently, I've been working on a <a href="https://inherentlee.codeberg.page/spoonfairies/" target="_blank" rel="external">website for a project called spoonfairies</a>. On the providers page, we list a series of names along with their pronouns, location, and services offered. Visually, it looks like this:</p>
|
|
||||||
<p><img src="https://leecat.art/img/spoonfairies-provider.png" alt="A provider listing from spoonfairies. On the top row of text, it shows the provider's name in large purple text, then their pronouns in slightly opaque white and slightly smaller font, then aligned on the right, a map pin emoji and their general location in standard size white text. On the second row of text, it lists a few services the provider offers, comma separated." loading="lazy" decoding="async" width="1000" height="147"></p>
|
|
||||||
<h2 id="pronouns">pronouns</h2>
|
|
||||||
<p>at first, all three pieces of information in the top row had no extra styling - it was just a line of text with the same color and size throughout. The location bit also didn't exist yet, so we're going to briefly ignore it. Screenreader testing (with NVDA, specifically) informed me that, when reading through a long list of providers, parentheses become <em>very</em> irritating. Imagine hearing the following:</p>
|
|
||||||
<blockquote>
|
|
||||||
<p>Lorem Ipsum left parentheses she slash her right parentheses web accessiblity webdev. Dolor Sit left parentheses they slash them right parentheses housecleaning. Amet Consectetur left parentheses he slash him right parentheses webdev spreadsheets software.</p>
|
|
||||||
</blockquote>
|
|
||||||
<p>...ad nauseam. Kinda irritating.</p>
|
|
||||||
<h3 id="the-fix">the fix</h3>
|
|
||||||
<p>put the pronouns in a span that provides special styling, and use <code>::before</code> and <code>::after</code> to apply parentheses.</p>
|
|
||||||
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/providers/lorem-ipsum<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
|
|
||||||
Lorem Ipsum
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pronouns<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>she/her<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span></code></pre>
|
|
||||||
<pre class="language-css"><code class="language-css"><span class="token selector">.pronouns::before</span> <span class="token punctuation">{</span>
|
|
||||||
<span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">"("</span> / <span class="token string">""</span><span class="token punctuation">;</span>
|
|
||||||
<span class="token punctuation">}</span>
|
|
||||||
<span class="token selector">.pronouns::after</span> <span class="token punctuation">{</span>
|
|
||||||
<span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">")"</span> / <span class="token string">""</span><span class="token punctuation">;</span>
|
|
||||||
<span class="token punctuation">}</span></code></pre>
|
|
||||||
<p><strong>the slash is the magic there.</strong> The string before the slash indicates the visual content, and the string after the slash is the alternative text content. I went happily on my way.</p>
|
|
||||||
<p>plus, this is neat - now I can style the pronouns separately. Let's make them the standard text color rather than the link color, and a bit smaller, and a smidge opaque... nice.</p>
|
|
||||||
<h2 id="location">location</h2>
|
|
||||||
<p>ooh, time to implement locations! I did my same ol' trick.</p>
|
|
||||||
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/providers/lorem-ipsum<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
|
|
||||||
Lorem Ipsum
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pronouns<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>she/her<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>location<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Tacoma<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span></code></pre>
|
|
||||||
<pre class="language-css"><code class="language-css"><span class="token selector">.location::before</span> <span class="token punctuation">{</span>
|
|
||||||
<span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">"📍"</span> / <span class="token string">"is based out of"</span><span class="token punctuation">;</span>
|
|
||||||
<span class="token punctuation">}</span></code></pre>
|
|
||||||
<p>I even added actual alternative text rather than an empty string to provide some context. Pronouns, I figured, could exist without much context, as it's pretty common for them to follow directly after names in introductions, but location isn't as much of a given.</p>
|
|
||||||
<p>again, style em up nice, more of a standard text look, right-aligned. Cool.</p>
|
|
||||||
<h2 id="a-bigger-problem-than-parentheses">a bigger problem than parentheses</h2>
|
|
||||||
<p>...then I did some screen reader testing. Which I should have done directly after the pronouns bit. Turns out, I wasn't thrilled with what the <code>&lt;span&gt;</code>s did.</p>
|
|
||||||
<p>at least with fairly default settings in NVDA, the <code>&lt;span&gt;</code>s broke up the way the link was read out. Suddenly, I was getting:</p>
|
|
||||||
<blockquote>
|
|
||||||
<p>visited link Lorem Ipsum visited link she slash her visited link Tacoma</p>
|
|
||||||
</blockquote>
|
|
||||||
<p>this is all one link, mind you. The <code>&lt;a&gt;</code> tag isn't broken into three links. But the <code>&lt;span&gt;</code>s apparently break up the screen reader output anyway (in NVDA, that's a continual caveat).</p>
|
|
||||||
<p>ooookay... what next?</p>
|
|
||||||
<h3 id="total-overhaul">total overhaul</h3>
|
|
||||||
<p>I moved away from my <code>content</code> approach entirely (well, I kept it around as a failsafe, but it's not running the show now). Instead, I switched over to an <code>aria-label</code> for the whole link.</p>
|
|
||||||
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/providers/lorem-ipsum<span class="token punctuation">"</span></span>
|
|
||||||
<span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Lorem Ipsum she/her is based out of Tacoma<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
|
|
||||||
Lorem Ipsum
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pronouns<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>she/her<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>location<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Tacoma<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>
|
|
||||||
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span></code></pre>
|
|
||||||
<p>(technically, all this is templated to hell and back. I would hope that's obvious given I'm talking about <em>lists</em> of these entries.)</p>
|
|
||||||
<p>now, after more screen reader testing, it reads out smoothly. The <code>aria-label</code> precludes the actual link text and cleanly says what needs to be said, with nothing breaking up the text and the whole thing easily recognized as one link. <em>And</em> I've got my fancy styling. Sweet.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>crow</title>
|
|
||||||
<link href="https://leecat.art/crow/" />
|
|
||||||
<updated>2026-02-09T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/crow/</id>
|
|
||||||
<content type="html"></content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>charlie the alpaca handspun</title>
|
|
||||||
<link href="https://leecat.art/charlie-the-alpaca-handspun/" />
|
|
||||||
<updated>2026-02-05T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/charlie-the-alpaca-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from Circle R Ranch. 100% alpaca, from Charlie the alpaca.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>ruby the alpaca handspun</title>
|
|
||||||
<link href="https://leecat.art/ruby-the-alpaca-handspun/" />
|
|
||||||
<updated>2026-01-27T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/ruby-the-alpaca-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from Circle R Ranch. 100% alpaca, from Ruby the alpaca.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>hand-dyed gold handspun</title>
|
|
||||||
<link href="https://leecat.art/hand-dyed-gold-handspun/" />
|
|
||||||
<updated>2026-01-24T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/hand-dyed-gold-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from <a href="https://paradisefibers.com" target="_blank" rel="external">Paradise Fibers</a>. 70% merino/30% nylon. Hand-dyed by me.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>spinner's dream handspun</title>
|
|
||||||
<link href="https://leecat.art/spinners-dream-handspun/" />
|
|
||||||
<updated>2026-01-18T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/spinners-dream-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from <a href="https://paradisefibers.com" target="_blank" rel="external">Paradise Fibers</a>. 40% merino/20% alpaca/20% camel/20% mulberry silk. Scrumptiously soft.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>rambouillet handspun</title>
|
|
||||||
<link href="https://leecat.art/rambouillet-handspun/" />
|
|
||||||
<updated>2026-01-18T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/rambouillet-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from <a href="https://woolgatherings.com" target="_blank" rel="external">Woolgatherings</a>. 100% rambouillet. Hand-dyed!</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>fire & ice handspun</title>
|
|
||||||
<link href="https://leecat.art/fire-and-ice-handspun/" />
|
|
||||||
<updated>2026-01-18T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/fire-and-ice-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from <a href="https://www.etsy.com/shop/JakiraFarms" target="_blank" rel="external">Jakira Farms</a> in Fire &amp; Ice colorway. 100% merino.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>dyeing fiber</title>
|
|
||||||
<link href="https://leecat.art/dyeing-fiber/" />
|
|
||||||
<updated>2026-01-18T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/dyeing-fiber/</id>
|
|
||||||
<content type="html"><p>hand-dyed with acid dyes</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<title>coral reef handspun</title>
|
|
||||||
<link href="https://leecat.art/coral-reef-handspun/" />
|
|
||||||
<updated>2026-01-18T00:00:00Z</updated>
|
|
||||||
<id>https://leecat.art/coral-reef-handspun/</id>
|
|
||||||
<content type="html"><p>Fiber from <a href="https://www.etsy.com/shop/JakiraFarms" target="_blank" rel="external">Jakira Farms</a> in Coral Reef colorway. 100% merino.</p>
|
|
||||||
</content>
|
|
||||||
</entry>
|
|
||||||
</feed>
|
|
||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Loaded 100 of 273 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user