Compare commits
6 commits
main
...
twitter-ar
| Author | SHA1 | Date | |
|---|---|---|---|
| c6501564f6 | |||
| f3da1087e3 | |||
| 90c2ba8787 | |||
| e8899a6ead | |||
| 74c796d5cd | |||
| 90806aa8f6 |
50 changed files with 141 additions and 705 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,3 @@
|
||||||
LightroomExports/
|
|
||||||
node_modules/
|
node_modules/
|
||||||
public/
|
public/
|
||||||
/documentation/mirrors/
|
/documentation/mirrors/
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -21,11 +21,9 @@ site:
|
||||||
hugo --buildFuture --enableGitInfo --destination "$(BUILD_DIR)"
|
hugo --buildFuture --enableGitInfo --destination "$(BUILD_DIR)"
|
||||||
|
|
||||||
deploy: site
|
deploy: site
|
||||||
@echo "Removing .DS_Store files from $(DEPLOY_LOCATION)"
|
|
||||||
find "$(BUILD_DIR)" -name .DS_Store -print -delete
|
|
||||||
@echo "Deploying to $(DEPLOY_LOCATION)"
|
@echo "Deploying to $(DEPLOY_LOCATION)"
|
||||||
rsync -avz --no-times --no-perms --delete "$(BUILD_DIR)/" "$(DEPLOY_LOCATION)"
|
rsync -avz --no-times --no-perms --delete "$(BUILD_DIR)/" "$(DEPLOY_LOCATION)"
|
||||||
git tag -f $(shell ./scripts/website deployment next-tag)
|
git tag -f deploy-$(shell date +%Y-%m-%d)
|
||||||
|
|
||||||
deployall: nethack deploy
|
deployall: nethack deploy
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
title: "{{ replace .Name "-" " " | title }}"
|
|
||||||
slug: link-{{ .Name }}
|
|
||||||
date: {{ .Date }}
|
|
||||||
categories: links
|
|
||||||
draft: true
|
|
||||||
tags: []
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
blog: blog/:year/:month/:slug/
|
blog: blog/:year/:month/:slug/
|
||||||
photos: photos/:year/:month/:slug/
|
photos: photos/:year/:month/:slug/
|
||||||
twitter: twitter/:year/:month/:slug/
|
tweets: tweets/:year/:month/:slug/
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,8 @@
|
||||||
---
|
---
|
||||||
|
title: Eryn Rachel Wells
|
||||||
layout: single
|
layout: single
|
||||||
draft: true
|
|
||||||
params:
|
|
||||||
renderHeadingAnchors: false
|
|
||||||
---
|
---
|
||||||
|
|
||||||
¡Hola! Me llamo Eryn Wells. Este es mi sitio web. ¡Bienvenidos!
|
{{< nobreak >}}Ingeniera de software,{{< /nobreak >}}
|
||||||
|
alfarera, música, y
|
||||||
|
{{< nobreak >}}nerd en general.{{< /nobreak >}}
|
||||||
## Personal
|
|
||||||
|
|
||||||
Soy mujer queer,
|
|
||||||
|
|
||||||
|
|
||||||
## Profesional
|
|
||||||
|
|
||||||
Desde 2011, he trabajado como ingeniera de software en varios companías alrededor del área
|
|
||||||
del Bahía de San Francisco. En 2016, me uní a [Apple][]. Hoy, trabajo en
|
|
||||||
tecnologías que
|
|
||||||
|
|
|
||||||
|
|
@ -6,61 +6,53 @@ params:
|
||||||
|
|
||||||
Hi, I'm Eryn Wells. This is my website. Welcome!
|
Hi, I'm Eryn Wells. This is my website. Welcome!
|
||||||
|
|
||||||
|
|
||||||
## Latest
|
## Latest
|
||||||
|
|
||||||
Here are some of my most recent posts.
|
Here are some of my most recent posts.
|
||||||
|
|
||||||
{{< home/latest >}}
|
{{< home/latest >}}
|
||||||
|
|
||||||
|
|
||||||
## Personal
|
## Personal
|
||||||
|
|
||||||
I'm a queer woman, {{< tess >}}' partner, and mom of [two cats][cats]. I
|
I'm a queer trans woman, {{< tess >}}' partner, and mom of [two cats][cats]. I
|
||||||
was born in Seattle, {{< abbr Washington >}}WA{{< /abbr >}} and grew up in
|
was born in Seattle, {{< abbr Washington >}}WA{{< /abbr >}} and grew up in
|
||||||
Phoenix, {{< abbr Arizona >}}AZ{{< /abbr >}}. I attended [Oberlin College][]
|
Phoenix, {{< abbr Arizona >}}AZ{{< /abbr >}}. I attended [Oberlin College][ob]
|
||||||
where I got a degree in Computer Science. My pronouns are [she/her][pronouns].
|
where I got a degree in Computer Science. My pronouns are [she/her][pronouns].
|
||||||
|
|
||||||
You can read more about me on my [about][ab] page, or [get in touch][where-am-i].
|
You can read more about me on my [about][ab] page, or [get in touch][where-am-i].
|
||||||
|
|
||||||
|
|
||||||
## Professional
|
## Professional
|
||||||
|
|
||||||
I've worked as a software engineer since 2011 for a variety of companies around
|
I've worked as a software engineer since 2011 for a variety of companies around
|
||||||
the San Francisco Bay Area. I joined [Apple][] in 2016, where I currently work
|
the San Francisco Bay Area. I joined [Apple][a] in 2016, where I currently work
|
||||||
on password management and authentication technologies.
|
on password management and authentication technologies.
|
||||||
|
|
||||||
My [résumé][r] has all the details.
|
My [résumé][r] has all the details.
|
||||||
|
|
||||||
|
|
||||||
## Hobbies
|
## Hobbies
|
||||||
|
|
||||||
When I'm not working, you can reliably find me hacking on this website or [some
|
When I'm not working, you can reliably find me hacking on this website or [some
|
||||||
other coding project][src]. I'm also a musician: I play piano, Irish tin
|
coding other project][gh]. I'm also a musician, and play piano, Irish tin
|
||||||
whistle, and modular synthesizer. Occasionally I [record things][sc] or offer
|
whistle, and modular synthesizer. Occasionally I [record][bc] [things][sc]. I
|
||||||
them [for sale][sc]. I love outer space and astronomy; I will always get excited
|
love outer space and astronomy; I will always get excited to look at the moon
|
||||||
to look at the moon with you, or check out anything through a telescope. I enjoy
|
with you, or check out anything through a telescope. I enjoy [photograhy][p],
|
||||||
[photograhy][p], mostly as a travel hobby. And I've been practicing
|
mostly as a travel hobby. And I've been practicing iaido, a traditional Japanese
|
||||||
[iaidō][mjer], a traditional Japanese sword art, at [Nishi Kaigan Iaidō
|
sword art, since early 2024. Other things I've been into include: bread baking,
|
||||||
Dōjō][nkid] since early 2024. Other things I've been into include: bread baking,
|
|
||||||
bicycling, calligraphy, ceramics, and knitting.
|
bicycling, calligraphy, ceramics, and knitting.
|
||||||
|
|
||||||
|
[a]: https://apple.com
|
||||||
[Apple]: https://apple.com
|
|
||||||
[ab]: {{< ref "/about" >}}
|
[ab]: {{< ref "/about" >}}
|
||||||
[b]: {{< ref "/blog" >}}
|
[b]: {{< ref "/blog" >}}
|
||||||
[bc]: https://erynwells.bandcamp.com/releases
|
[bc]: https://erynwells.bandcamp.com/releases
|
||||||
[cats]: {{< ref "/cats" >}}
|
[cats]: {{< ref "/cats" >}}
|
||||||
[eml]: mailto:Eryn%20Wells<eryn@erynwells.me>
|
[eml]: mailto:Eryn%20Wells<eryn@erynwells.me>
|
||||||
[src]: https://source.erynwells.me/eryn
|
[gh]: https://github.com/erynofwales
|
||||||
[ig]: https://www.instagram.com/erynofwales
|
[ig]: https://www.instagram.com/erynofwales
|
||||||
[m]: https://mastodon.social/@erynofwales
|
[m]: https://mastodon.social/@erynofwales
|
||||||
[n]: {{< ref "/now" >}}
|
[n]: {{< ref "/now" >}}
|
||||||
[Oberlin College]: https://www.oberlin.edu
|
[ob]: https://www.oberlin.edu
|
||||||
[p]: {{< ref "/photos" >}}
|
[p]: {{< ref "/photos" >}}
|
||||||
[pronouns]: http://pronoun.is/she
|
[pronouns]: http://pronoun.is/she
|
||||||
[r]: {{< ref "/resume" >}}
|
[r]: {{< ref "/resume" >}}
|
||||||
[sc]: https://soundcloud.com/purlsnbeeps
|
[sc]: https://soundcloud.com/purlsnbeeps
|
||||||
[where-am-i]: {{< ref "/about/where-am-i" >}}
|
[where-am-i]: {{< ref "/about/where-am-i" >}}
|
||||||
[mjer]: https://en.wikipedia.org/wiki/Mus%C5%8D_Jikiden_Eishin-ry%C5%AB
|
|
||||||
[nkid]: https://iaido.org
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
---
|
---
|
||||||
title: "Pajaro Dunes"
|
title: "Pajaro Dunes"
|
||||||
date: 2023-05-30T08:31:34-07:00
|
date: 2023-05-30T08:31:34-07:00
|
||||||
tags: [Travel, Beaches, Tess, EJ, Vacations]
|
categories: Travel
|
||||||
|
tags: [Beaches, Tess, EJ, Vacations]
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< tess >}}, EJ, and I took a weekend trip down the coast over Memorial Day
|
{{< tess >}}, EJ, and I took a weekend trip down the coast over Memorial Day
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
---
|
|
||||||
title: "AI Makes Me Sad"
|
|
||||||
description: Sad tooting about AI.
|
|
||||||
date: 2025-09-05T13:56:40-07:00
|
|
||||||
draft: true
|
|
||||||
tags:
|
|
||||||
- AI
|
|
||||||
- Tech
|
|
||||||
---
|
|
||||||
|
|
||||||
[My own toot](https://mastodon.social/@erynofwales/115153168015169009) from a
|
|
||||||
few days on Mastodon:
|
|
||||||
|
|
||||||
> I don't know what to do with how much I dislike AI and its relentless creep
|
|
||||||
> into my industry. The more I see of it, the more inevitable it seems, and the
|
|
||||||
> more alienated I feel from the software engineering industry.
|
|
||||||
>
|
|
||||||
> It could very well push me out of the industry, not because it steals my job,
|
|
||||||
> but because it robs me of the joy I had for this work.
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
---
|
---
|
||||||
title: "America Tips Into Fascism by Garrett Graff"
|
title: "Link: America Tips Into Fascism"
|
||||||
slug: america-tips-into-fascism
|
slug: america-tips-into-fascism
|
||||||
date: 2025-08-25T22:31:15-06:00
|
date: 2025-08-25T22:31:15-06:00
|
||||||
categories: Links
|
|
||||||
tags:
|
tags:
|
||||||
- Politics
|
- Politics
|
||||||
- USA
|
- USA
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
---
|
|
||||||
title: "Hamonshū"
|
|
||||||
date: 2025-09-18
|
|
||||||
tags:
|
|
||||||
- Art
|
|
||||||
- Web Design
|
|
||||||
- Design
|
|
||||||
- japan
|
|
||||||
---
|
|
||||||
|
|
||||||
Eric Meyer's [website](https://meyerweb.com) has a hand-drawn ink motif that I
|
|
||||||
really dig. It's based heavily on drawings from the Hamonshū, a set of books
|
|
||||||
produced by Yūzan Mōri. This work was new to me, and I enjoyed flipping through
|
|
||||||
it on the Internet Archive, embedded below.
|
|
||||||
|
|
||||||
<figure class="figure figure--small">
|
|
||||||
<iframe
|
|
||||||
src="https://archive.org/embed/hamonshuyv1mori"
|
|
||||||
width="800"
|
|
||||||
height="700"
|
|
||||||
frameborder="0"
|
|
||||||
webkitallowfullscreen="true"
|
|
||||||
mozallowfullscreen="true"
|
|
||||||
allowfullscreen>
|
|
||||||
</iframe>
|
|
||||||
</figure>
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
---
|
|
||||||
title: "I Am an AI Hater by Anthony Moser"
|
|
||||||
slug: link-i-am-an-ai-hater
|
|
||||||
date: 2025-08-28T08:36:59-06:00
|
|
||||||
categories: links
|
|
||||||
tags:
|
|
||||||
- AI
|
|
||||||
- Tech
|
|
||||||
---
|
|
||||||
|
|
||||||
A [fierce argument][link] against AI by Anthony Moser.
|
|
||||||
|
|
||||||
> But I am more than a critic: I am a hater. I am not here to make a careful
|
|
||||||
> comprehensive argument, because people have already done that. ... I am here
|
|
||||||
> to be rude, because this is a rude technology, and it deserves a rude
|
|
||||||
> response.
|
|
||||||
|
|
||||||
[link]: https://anthonymoser.github.io/writing/ai/haterdom/2025/08/26/i-am-an-ai-hater.html
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
---
|
---
|
||||||
title: "Rings by ND Stevenson"
|
title: "Link: Rings by ND Stevenson"
|
||||||
slug: ndstevenson-rings
|
slug: ndstevenson-rings
|
||||||
date: 2025-08-28T07:43:45-06:00
|
date: 2025-08-28T07:43:45-06:00
|
||||||
categories: Links
|
|
||||||
tags:
|
tags:
|
||||||
- Comics
|
- Comics
|
||||||
- LGBTQIA+
|
- LGBTQIA+
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "I'm a Student Again"
|
|
||||||
description: I started taking Japanese classes at CCSF.
|
|
||||||
slug: student-again
|
|
||||||
date: 2025-09-02
|
|
||||||
tags:
|
|
||||||
- Life
|
|
||||||
- School
|
|
||||||
- japanese
|
|
||||||
- CCSF
|
|
||||||
---
|
|
||||||
|
|
||||||
I've been fortunate to take two trips to Japan over the last couple years.
|
|
||||||
Leading up to those trips, I picked up learning Japanese, attempting to build
|
|
||||||
some basic language skills for getting around. At first, I used [Duolingo][dja]
|
|
||||||
but recently switched to [Migaku][mja].
|
|
||||||
|
|
||||||
When I returned from our most recent trip, I decided to find a class so I can
|
|
||||||
practice speaking skills. [Community College of San Francisco][ccsf] has an
|
|
||||||
excellent program called "[Free City][fc]" that grants free tuition to residents
|
|
||||||
of the city. It also has [Japanese program][ccsfja]. So I enrolled in their
|
|
||||||
online Japanese 1A course.
|
|
||||||
|
|
||||||
This is my first time taking formal classes since I graduated college. I'm
|
|
||||||
looking forward to learning in a more structured way again, and also getting a
|
|
||||||
chance to practice speaking with people rather than talking at my phone screen.
|
|
||||||
|
|
||||||
[dja]: https://www.duolingo.com/course/ja/en/Learn-Japanese
|
|
||||||
[mja]: https://migaku.com/learn-japanese
|
|
||||||
[ccsf]: https://www.ccsf.edu
|
|
||||||
[ccsfja]: https://www.ccsf.edu/degrees-certificates/japanese
|
|
||||||
[fc]: https://www.ccsf.edu/free-city
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
---
|
|
||||||
title: "I'm a Student Again"
|
|
||||||
description: I started taking Japanese classes at CCSF.
|
|
||||||
slug: student-again
|
|
||||||
date: 2025-09-02
|
|
||||||
resources:
|
|
||||||
- name: textbooks
|
|
||||||
src: textbooks.jpg
|
|
||||||
title: My textbooks
|
|
||||||
params:
|
|
||||||
alt: >
|
|
||||||
Three textbooks fanned out on a dark wood desktop. From left to
|
|
||||||
right: Japanese for Busy People Book 1, Genki Book 1 Workbook, and
|
|
||||||
Genki Book 1 Textbook.
|
|
||||||
tags:
|
|
||||||
- Life
|
|
||||||
- School
|
|
||||||
- japanese
|
|
||||||
- CCSF
|
|
||||||
---
|
|
||||||
|
|
||||||
{{< figures/image name=textbooks >}}
|
|
||||||
|
|
||||||
I've been fortunate to take two trips to Japan over the last couple years.
|
|
||||||
Leading up to those trips, I picked up learning Japanese, attempting to build
|
|
||||||
some basic language skills for getting around. At first, I used [Duolingo][dja]
|
|
||||||
but recently switched to [Migaku][mja].
|
|
||||||
|
|
||||||
When I returned from our most recent trip, I decided to find a class so I can
|
|
||||||
practice speaking skills. [Community College of San Francisco][ccsf] has an
|
|
||||||
excellent program called "[Free City][fc]" that grants free tuition to residents
|
|
||||||
of the city. It also has [Japanese program][ccsfja]. So I enrolled in their
|
|
||||||
online Japanese 1A (Intro to Japanese) and in-person Japanese 10A (Beginning
|
|
||||||
Conversational Japanese) courses.
|
|
||||||
|
|
||||||
The scheduling constraints are more complex this time around. Juggling the
|
|
||||||
responsibilities of work, childcare, volunteer work, and other hobbies is a
|
|
||||||
challenge. It makes me appreciate the freedom I had in my late teens and
|
|
||||||
early-twenties.
|
|
||||||
|
|
||||||
Nevertheless, I'm looking forward to learning in a more structured way again,
|
|
||||||
and also getting a chance to practice speaking with real people rather than
|
|
||||||
talking to the AI bots in my phone.
|
|
||||||
|
|
||||||
[dja]: https://www.duolingo.com/course/ja/en/Learn-Japanese
|
|
||||||
[mja]: https://migaku.com/learn-japanese
|
|
||||||
[ccsf]: https://www.ccsf.edu
|
|
||||||
[ccsfja]: https://www.ccsf.edu/degrees-certificates/japanese
|
|
||||||
[fc]: https://www.ccsf.edu/free-city
|
|
||||||
BIN
content/blog/2025/student-again/textbooks.jpg
(Stored with Git LFS)
BIN
content/blog/2025/student-again/textbooks.jpg
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
title: "Two Neat Websites From Miriam"
|
|
||||||
date: 2025-09-23T10:16:55-07:00
|
|
||||||
tags:
|
|
||||||
- Pottery
|
|
||||||
- Web Design
|
|
||||||
---
|
|
||||||
|
|
||||||
A couple neat websites I learned about from [Miriam](https://www.miriamsuzanne.com):
|
|
||||||
|
|
||||||
* [Learn Pottery](https://learnpottery.com) offers online pottery lessons. Makes
|
|
||||||
me want to pick up throwing again.
|
|
||||||
* [Utopia.fyi](https://utopia.fyi) helps you develop font size and spacing scales
|
|
||||||
for responsive web design. I read about it in OddBird's recent blog post about
|
|
||||||
[Designing for User Font-size and Zoom][ob].
|
|
||||||
|
|
||||||
[ob]: https://www.oddbird.net/2025/07/22/size-preferences/
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
---
|
|
||||||
title: "Notes on 2025W38"
|
|
||||||
slug: weeknotes-2025w38
|
|
||||||
date: 2025-09-21
|
|
||||||
categories: weeknotes
|
|
||||||
tags:
|
|
||||||
- Weeknotes
|
|
||||||
- Trans
|
|
||||||
- japan
|
|
||||||
- japan-tokyo
|
|
||||||
- Trains
|
|
||||||
- Yamanote
|
|
||||||
- uspol
|
|
||||||
- Travel
|
|
||||||
- Unions
|
|
||||||
---
|
|
||||||
|
|
||||||
I'm pretty behind on weeknotes again.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
It has been a truly awful few weeks for trans people in the US. I am worried for
|
|
||||||
myself and for every other trans person navigating the daily terror of the
|
|
||||||
political climate here. You are loved and valid, no matter what they say.
|
|
||||||
:heart:
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
Someone [compiled all the station ditties](https://yamanot.es) along the
|
|
||||||
Yamanote line in Tōkyō. Via [Jonathan Wight][wight], though the link is now
|
|
||||||
dead.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[Jimmy Kimmel was removed from the air][kimmel] by a combination of ABC, Disney,
|
|
||||||
and Nexstar over comments he made about Charlie Kirk. His comments were mild at
|
|
||||||
best, and his removal portends bad things for freedom of speech and a free press
|
|
||||||
in the US.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The US seems poised to pass a country-wide [bathroom ban][bathrooms] for trans
|
|
||||||
people. It would deny trans people the right to use the toilets matching their
|
|
||||||
gender, and _also_ deny them access to toilets matching their birth sex,
|
|
||||||
effectively preventing trans people from using the bathroom in any public space.
|
|
||||||
If this passes, I don't think I will be able to travel to the UK for any reason
|
|
||||||
for the forseeable future.
|
|
||||||
|
|
||||||
Sol Elias draws a comparison to the current [moral panic][panic] around trans
|
|
||||||
rights and the "crack baby" era of the 1980s and 1990s.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The team behind the Diablo franchise at Blizzard has [unionized][diablo].
|
|
||||||
Congrats to them!
|
|
||||||
|
|
||||||
[wight]: https://mastodon.social/@schwa/115125526450662142
|
|
||||||
[kimmel]: https://mastodon.social/@verge/115112175537370858
|
|
||||||
[bathrooms]: https://www.liberalcurrents.com/britains-bathroom-ban/
|
|
||||||
[panic]: https://scalawagmagazine.org/2025/08/freak-generations-the-moral-panic-playbook-from-crack-babies-to-trans-kids/
|
|
||||||
[diablo]: https://mastodon.social/@verge/115112175537370858
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
title: "Thirty Eight"
|
|
||||||
date: 2026-01-14
|
|
||||||
draft: true
|
|
||||||
tags:
|
|
||||||
- Me
|
|
||||||
- Birthdays
|
|
||||||
---
|
|
||||||
|
|
||||||
I'm turning thirty eight today!
|
|
||||||
|
|
||||||
Neil Armstrong was 38 when he walked on the moon. (Buzz Aldrin was 39.) Jack
|
|
||||||
Swigert was 38 when he timed the 14 second burn that brought Apollo 13 back into
|
|
||||||
position for reentry to Earth.
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
title: "Sunset over Pajaro Dunes"
|
title: "Sunset over Pajaro Dunes"
|
||||||
linkTitle: Pajaro Sunset
|
linkTitle: Pajaro Sunset
|
||||||
date: 2023-05-28T20:12:13-07:00
|
date: 2023-05-28T20:12:13-07:00
|
||||||
tags: [Travel, Beaches]
|
categories: Travel
|
||||||
|
tags: ["Beaches"]
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< tess >}}, EJ, and I took a little weekend trip over Memorial Day this year
|
{{< tess >}}, EJ, and I took a little weekend trip over Memorial Day this year
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
title: "Bow River Valley"
|
|
||||||
date: 2025-09-07T12:06:49-07:00
|
|
||||||
tags:
|
|
||||||
- Travel
|
|
||||||
- Alberta
|
|
||||||
- Canada
|
|
||||||
- Banff
|
|
||||||
---
|
|
||||||
|
|
||||||
The [Bow River](https://en.wikipedia.org/wiki/Bow_River) runs down from the
|
|
||||||
Rockies, feeding Banff, Canmore, and Calgary. In this photo, the valley runs
|
|
||||||
roughly northwest. It was taken from the top of the [Banff
|
|
||||||
Gondola](https://www.banffjaspercollection.com/attractions/banff-gondola/).
|
|
||||||
BIN
content/photos/2025/bow-river-valley/website-bow-river-valley.0640.jpg
(Stored with Git LFS)
BIN
content/photos/2025/bow-river-valley/website-bow-river-valley.0640.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
content/photos/2025/drink-coca-cola/coca-cola-sign.jpg
(Stored with Git LFS)
BIN
content/photos/2025/drink-coca-cola/coca-cola-sign.jpg
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,20 +0,0 @@
|
||||||
---
|
|
||||||
title: "Drink Coca-Cola"
|
|
||||||
date: 2025-09-10T18:26:15-07:00
|
|
||||||
tags:
|
|
||||||
- Urban
|
|
||||||
- Advertising
|
|
||||||
- San Francisco
|
|
||||||
- Coca-Cola
|
|
||||||
---
|
|
||||||
|
|
||||||
I was standing on a neighborhood street corner recently and spotted this sign
|
|
||||||
hiding behind a parked car across the street. When the car moved, I snapped this
|
|
||||||
photo.
|
|
||||||
|
|
||||||
It's kind of a curious thing, isn't it? It's an advertisement for Coke on a
|
|
||||||
low traffic residential corner that seems to have been there for a long time.
|
|
||||||
(It looks old.) It got me wondering what that corner was like 50 or 100 years
|
|
||||||
ago. Clearly the owner of the building has maintained it too: the paint has been
|
|
||||||
touched up here and there, and someone added the green frame at some point.
|
|
||||||
|
|
||||||
BIN
content/photos/2025/drink-coca-cola/thumbnail.jpg
(Stored with Git LFS)
BIN
content/photos/2025/drink-coca-cola/thumbnail.jpg
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 268 KiB |
|
|
@ -1,23 +0,0 @@
|
||||||
---
|
|
||||||
title: "Harvest Moon"
|
|
||||||
date: 2025-10-06T22:00:00-07:00
|
|
||||||
tags:
|
|
||||||
- Space
|
|
||||||
- Astrophotography
|
|
||||||
- Moon
|
|
||||||
---
|
|
||||||
|
|
||||||
Monday October 6 was the full moon. As the closest full moon to the [autumnal
|
|
||||||
equinox][], it is the [Harvest Moon][]. It also happened to be a [supermoon][],
|
|
||||||
making it slightly bigger in the night sky.
|
|
||||||
|
|
||||||
I shot this photo from my back deck with my Fujifilm X-T5 and a Canon 100mm
|
|
||||||
macro prime[^1]. Amazingly, this is a handheld shot too. I couldn't find a
|
|
||||||
necessary bit of my tripod to mount the camera, so I made do.
|
|
||||||
|
|
||||||
[^1]: Photography nerds will notice these are _not_ compatible components; I use
|
|
||||||
a Fringer EF-FX mount adapter for this.
|
|
||||||
|
|
||||||
[autumnal equinox]: https://en.wikipedia.org/wiki/September_equinox
|
|
||||||
[Harvest Moon]: https://en.wikipedia.org/wiki/Full_moon#Harvest_moon
|
|
||||||
[supermoon]: https://science.nasa.gov/moon/supermoons/
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
---
|
|
||||||
title: "Lait's Go"
|
|
||||||
date: 2025-08-27T18:00:41-06:00
|
|
||||||
tags:
|
|
||||||
- Travel
|
|
||||||
- Puns
|
|
||||||
- Milk
|
|
||||||
---
|
|
||||||
|
|
||||||
Spotted in a small café at the top of Sulphur Mountain in Banff, Alberta: a
|
|
||||||
delightful bilingual pun. In English, this milk is called "Milk 2 Go". In
|
|
||||||
French, it's called "Lait's Go".
|
|
||||||
BIN
content/photos/2025/laits-go/laits-go.jpg
(Stored with Git LFS)
BIN
content/photos/2025/laits-go/laits-go.jpg
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,18 +0,0 @@
|
||||||
---
|
|
||||||
title: "Lake Louise"
|
|
||||||
date: 2025-08-27T10:15:06-06:00
|
|
||||||
draft: true
|
|
||||||
tags:
|
|
||||||
- Travel
|
|
||||||
- Nature
|
|
||||||
- Lake Louise
|
|
||||||
- Alberta
|
|
||||||
- Canada
|
|
||||||
---
|
|
||||||
|
|
||||||
Some friends and I had the chance to travel to [Lake Louise][] this summer. It's
|
|
||||||
stunningly blue -- unlike any body of water I've ever seen -- and surrounded by
|
|
||||||
picturesque mountains. We had only a few hours here so we did a short hike
|
|
||||||
around the lake, and then headed to Moraine Lake.
|
|
||||||
|
|
||||||
[Lake Louise]: https://www.banfflakelouise.com
|
|
||||||
BIN
content/photos/2025/lake-louise/lake-louise.jpg
(Stored with Git LFS)
BIN
content/photos/2025/lake-louise/lake-louise.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
content/photos/2025/lake-louise/thumbnail.jpg
(Stored with Git LFS)
BIN
content/photos/2025/lake-louise/thumbnail.jpg
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
title: "Mushrooms"
|
|
||||||
date: 2025-08-27T09:55:45-06:00
|
|
||||||
draft: true
|
|
||||||
tags:
|
|
||||||
- Nature
|
|
||||||
- Mushrooms
|
|
||||||
- Fungi
|
|
||||||
- Lake Louise
|
|
||||||
- Alberta
|
|
||||||
- Canada
|
|
||||||
---
|
|
||||||
|
|
||||||
A small colony of mushrooms growing on a stump. Found at Lake Louise, Alberta,
|
|
||||||
Canada.
|
|
||||||
BIN
content/photos/2025/mushrooms/mushrooms.jpg
(Stored with Git LFS)
BIN
content/photos/2025/mushrooms/mushrooms.jpg
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
title: Erin Anne O'Connor
|
|
||||||
linkTitle: EAOC
|
|
||||||
slug: eaoc
|
|
||||||
---
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
title: US Politics
|
|
||||||
---
|
|
||||||
42
content/tweets/_content.gotmpl.tmp
Normal file
42
content/tweets/_content.gotmpl.tmp
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{{/* vim: ft=gohtmltmpl: */}}
|
||||||
|
|
||||||
|
{{ $tweets := slice }}
|
||||||
|
{{ with resources.Get "twitter/tweets.json" }}
|
||||||
|
{{ with . | transform.Unmarshal }}
|
||||||
|
{{ $tweets = . }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $tweets }}
|
||||||
|
{{ $tweet := .tweet }}
|
||||||
|
|
||||||
|
{{
|
||||||
|
$content := dict
|
||||||
|
"mediaType" "text/markdown"
|
||||||
|
"value" (partial "twitter/assembleTweetMarkdown.html" $tweet)
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{ $creationDate := partial "twitter/parseCreatedAtDate.html" $tweet.created_at }}
|
||||||
|
{{ $title := printf "Tweet on %s" (time.Format "2 January 2005" $creationDate) }}
|
||||||
|
{{ $path := printf "%s/%s" $creationDate.Year $tweet.id_str }}
|
||||||
|
|
||||||
|
{{ $dates := dict "date" $creationDate }}
|
||||||
|
|
||||||
|
{{
|
||||||
|
$params := dict
|
||||||
|
"favoriteCount" $tweet.favorite_count
|
||||||
|
"retweetCount" $tweet.retweet_count
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{
|
||||||
|
$page := dict
|
||||||
|
"title" $title
|
||||||
|
"dates" $dates
|
||||||
|
"content" $content
|
||||||
|
"kind" "page"
|
||||||
|
"params" $params
|
||||||
|
"path" $path
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{ $.AddPage $page }}
|
||||||
|
{{ end }}
|
||||||
3
content/tweets/_index.md
Normal file
3
content/tweets/_index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
title: Tweets
|
||||||
|
---
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
---
|
|
||||||
title: "mi kepeken e ni"
|
|
||||||
draft: true
|
|
||||||
toc: open
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tech
|
|
||||||
|
|
||||||
### Hardware
|
|
||||||
|
|
||||||
[Apple M2 MacBook Air from 2022](https://www.apple.com/macbook-air-13-and-15-m2/)
|
|
||||||
: mi olin e ilo sona ni. tenpo pini la mi olin e ilo sona ante. ilo sona ante en
|
|
||||||
ilo sona ni li MacBook Air. tenpo ale la mi jo e ilo sona ante. kin la tenpo ale
|
|
||||||
la mi jo e ilo sona ni.
|
|
||||||
|
|
||||||
[Apple Studio Display](https://www.apple.com/studio-display/)
|
|
||||||
: I was on the fence about a Cinema Display for a long time. I ordered and
|
|
||||||
canceled three times. Ultimately I gave in, and I'm quite happy with it. It's
|
|
||||||
mounted on a VESA arm attached to my desktop.
|
|
||||||
|
|
||||||
### Software
|
|
||||||
|
|
||||||
#### Development
|
|
||||||
|
|
||||||
[Neovim](https://neovim.io/)
|
|
||||||
: tenpo suli la, mi kepeken e `vim`. ona li ilo nanpa wan pi pali lipu mi.
|
|
||||||
|
|
||||||
[Visual Studio Code](https://code.visualstudio.com/)
|
|
||||||
: tenpo sike mute la mi alasa e VSCode. ona li jo e ijo pona mute.
|
|
||||||
|
|
||||||
[Xcode](https://developer.apple.com/xcode/)
|
|
||||||
: mi pali lon [kulupu kili][apple]. Xcode li ilo pi pali lipu tawa. lon kulupu
|
|
||||||
kili la mi kepeken e Xcode. lon tomo mi, mi kepeken kin e Xcode. Xcode li pona.
|
|
||||||
|
|
||||||
[Fork](https://fork.dev)
|
|
||||||
: A GUI client for `git`. I think Fork has totally changed how I use `git`. I
|
|
||||||
still use the command line for many things, but working through diffs, staging
|
|
||||||
changes, and even rebasing is so much easier in a GUI.
|
|
||||||
|
|
||||||
#### Terminal
|
|
||||||
|
|
||||||
[Terminal.app](https://support.apple.com/guide/terminal/welcome/mac)
|
|
||||||
: macOS's built in terminal emulator is solid. The only thing I miss from it now
|
|
||||||
and then is "true color" support, and that's only when I try to install a new
|
|
||||||
color theme in Neovim and everything goes haywire.
|
|
||||||
|
|
||||||
[Zsh](https://www.zsh.org)
|
|
||||||
: I've been using Zsh since before it was cool. My shell config is full of
|
|
||||||
bespoke tweaks, including a prompt theme I'm rather proud of.
|
|
||||||
|
|
||||||
#### Hosting
|
|
||||||
|
|
||||||
[Digital Ocean](https://www.digitalocean.com)
|
|
||||||
: DO has hosted my VPS for a number of years. I moved there from Linode because
|
|
||||||
I wanted to run FreeBSD on my server.
|
|
||||||
|
|
||||||
[FreeBSD](https://www.freebsd.org)
|
|
||||||
: My server OS of choice. It's secure, simple, and resilient, and I appreciate
|
|
||||||
the less-encumbered BSD license.
|
|
||||||
|
|
||||||
[FastMail](https://www.fastmail.com/)
|
|
||||||
: I've used FastMail for years now as my email host. Their annual fees are quite
|
|
||||||
modest and they have a great feature set including a Sieve email filter editor,
|
|
||||||
and Masked Email for genearating ad hoc email addresses. I've never had a
|
|
||||||
problem with uptime, and the few times I've contacted support, they've been
|
|
||||||
helpful.
|
|
||||||
|
|
||||||
[Hugo](https://gohugo.io)
|
|
||||||
: This whole website is built with Hugo.
|
|
||||||
|
|
||||||
### Mobile
|
|
||||||
|
|
||||||
[Doppler](https://brushedtype.co/doppler/)
|
|
||||||
: File-based music player.
|
|
||||||
|
|
||||||
[Ivory](https://tapbots.com/ivory/)
|
|
||||||
: My Mastodon client of choice for macOS and iOS.
|
|
||||||
|
|
||||||
[Overcast](https://overcast.fm/podcasts)
|
|
||||||
: My podcast player of choice.
|
|
||||||
|
|
||||||
[Reeder](https://www.reederapp.com)
|
|
||||||
: RSS feed organizer and reader. I'm doing a lot more RSS these days.
|
|
||||||
|
|
||||||
[Transit](https://transitapp.com)
|
|
||||||
: Helps me stay on top of bus schedules in San Francisco.
|
|
||||||
|
|
||||||
## Music
|
|
||||||
|
|
||||||
[Logic Pro](https://www.apple.com/logic-pro/)
|
|
||||||
: Apple's DAW is full of features and plugins (far more than I could ever use)
|
|
||||||
and it's hard to beat the corporate discount, much as I also love Ableton.
|
|
||||||
|
|
||||||
[Shure SM7B](https://www.shure.com/en-US/products/microphones/sm7b)
|
|
||||||
: The SM7 is an iconic mic, and has been the go-to for voice actors, podcasters,
|
|
||||||
and musicians for 50 years. The excellent podcast Twenty Thousand Hertz did a
|
|
||||||
great [deep dive episode][20ksm7] on its history and place in the audio
|
|
||||||
industry. I have one on my desk at home, and it makes me sound great on work
|
|
||||||
video calls, and the occasional audio recording.
|
|
||||||
|
|
||||||
[Moog Matriarch](https://www.moogmusic.com/synthesizers?type=202)
|
|
||||||
: I'm a bit of a Moog fangirl, and this might be my favorite of their synths.
|
|
||||||
It's just hard to beat the sound of a Moog.
|
|
||||||
|
|
||||||
[Kawaii CA-65](https://kawaius.com/product/ca65/)
|
|
||||||
: I've been playing piano since I was seven years old. A digital piano is
|
|
||||||
perfect for the small apartments I've called home. This one has a fantastic
|
|
||||||
realistic action and it sounds great.
|
|
||||||
|
|
||||||
## Coffee
|
|
||||||
|
|
||||||
[Baratza Encore](https://www.baratza.com/product/encoretm-zcg485)
|
|
||||||
: It's affordable and does a pretty good job.
|
|
||||||
|
|
||||||
[Kalita Wave](https://kalitausa.com/products/kalita-wave-185-stainless-steel-coffee-dripper)
|
|
||||||
: The Kalita is probably the easist single serve pour over dripper I've used.
|
|
||||||
|
|
||||||
[Chemex](https://www.chemexcoffeemaker.com/six-cup-classic-series-coffeemaker.html)
|
|
||||||
: If I'm making coffee for more than just me, the Chemex is the biggest pour
|
|
||||||
over vessel I have. Makes yummy coffee too.
|
|
||||||
|
|
||||||
## Gaming
|
|
||||||
|
|
||||||
[Nintendo Switch](https://www.nintendo.com/us/switch/)
|
|
||||||
: Most of my gaming happens here. I play a lot of Mario Kart online with
|
|
||||||
friends, and I'm a big fan of both of the major Legend of Zelda titles that have
|
|
||||||
come out for it: Breath of the Wild and Tears of the Kingdom.
|
|
||||||
|
|
||||||
[PlayStation 5](https://www.playstation.com/en-us/ps5/)
|
|
||||||
: I also have a PS5. I've played a ton of Horizon: Zero Dawn and the new Final
|
|
||||||
Fantasy 7 games.
|
|
||||||
|
|
||||||
[Analogue Pocket](https://www.analogue.co/pocket)
|
|
||||||
: When I want to play my stock of Game Boy games, this thing is great.
|
|
||||||
|
|
||||||
[apple]: https://www.apple.com
|
|
||||||
[vscode-vim]: https://marketplace.visualstudio.com/items?itemName=vscodevim.vim
|
|
||||||
[20ksm7]: https://www.20k.org/episodes/sm7
|
|
||||||
14
deploy.sh
Executable file
14
deploy.sh
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env zsh
|
||||||
|
# Deploy erynwells.me to my web root
|
||||||
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
|
print -P "%BFiltering .DS_Store files%b"
|
||||||
|
find . -name '.DS_Store' -print -delete
|
||||||
|
|
||||||
|
print -P "%BGenerating site%b"
|
||||||
|
hugo
|
||||||
|
|
||||||
|
echo
|
||||||
|
print -P "%BRsyncing site to nutmeg.erynwells.me%b"
|
||||||
|
rsync -avz --no-times --no-perms --delete public/ \
|
||||||
|
eryn@nutmeg.erynwells.me:/srv/www/erynwells.me/html
|
||||||
|
|
@ -11,3 +11,6 @@ nethackScore: Score
|
||||||
nethackDungeonLevel: Dungeon Level
|
nethackDungeonLevel: Dungeon Level
|
||||||
nethackCharacterLevel: Character Level
|
nethackCharacterLevel: Character Level
|
||||||
nethackHP: HP
|
nethackHP: HP
|
||||||
|
|
||||||
|
favorites: Favorites
|
||||||
|
retweets: Retweets
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<abbr title="{{ .Get 0 }}">{{ .Inner }}</abbr>{{- "" -}}
|
<abbr title="{{ .Get 0 }}">{{ .Inner }}</abbr>
|
||||||
|
|
|
||||||
14
layouts/tweets/list.html
Normal file
14
layouts/tweets/list.html
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="main--list">
|
||||||
|
<header class="page-header">
|
||||||
|
{{ partial "page_header.html" (dict "page" .) }}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{{ $paginator := .Paginate .Pages.ByPublishDate.Reverse 100 }}
|
||||||
|
{{ range $paginator.Pages }}
|
||||||
|
{{ .Render "page_summary" }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ partial "pagination.html" . }}
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
||||||
18
layouts/tweets/page_summary.html
Normal file
18
layouts/tweets/page_summary.html
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<article class="page-summary">
|
||||||
|
{{ .Content }}
|
||||||
|
|
||||||
|
{{- if .Date -}}
|
||||||
|
{{/* TODO: Include time in this date */}}
|
||||||
|
{{- partial "page/date.html" (dict "page" . "style" "datetime") -}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
<div class="tag" data-name="favorites">
|
||||||
|
<span class="tag__name">{{ T "favorites" }}</span>
|
||||||
|
<span class="tag__value">{{ .Params.favoriteCount }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tag" data-name="retweets">
|
||||||
|
<span class="tag__name">{{ T "retweets" }}</span>
|
||||||
|
<span class="tag__value">{{ .Params.retweetCount }}</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Eryn Wells <eryn@erynwells.me>
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import datetime
|
|
||||||
import subprocess
|
|
||||||
from typing import List
|
|
||||||
from .scripting import Command
|
|
||||||
|
|
||||||
|
|
||||||
DATE_FORMAT = "%Y-%m-%d"
|
|
||||||
|
|
||||||
|
|
||||||
class DeploymentCommand(Command):
|
|
||||||
@property
|
|
||||||
def help(self) -> str:
|
|
||||||
return 'Deployment tools'
|
|
||||||
|
|
||||||
def add_arguments(self, parser: argparse.ArgumentParser):
|
|
||||||
commands = parser.add_subparsers(title="Deployment", required=True)
|
|
||||||
|
|
||||||
deployment_command = commands.add_parser(
|
|
||||||
'next-tag',
|
|
||||||
help='Calculate the next deployment tag for a given date, examining all other tags for that day'
|
|
||||||
)
|
|
||||||
deployment_command.add_argument(
|
|
||||||
'--date', '-d',
|
|
||||||
type=self.__class__.parse_date_argument,
|
|
||||||
default=datetime.date.today(),
|
|
||||||
help="date to calculate a new deployment tag for (default: today)"
|
|
||||||
)
|
|
||||||
deployment_command.set_defaults(handler=self.handle_next_deployment_tag_command)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_date_argument(date_string: str) -> datetime.date:
|
|
||||||
return datetime.datetime.strptime(date_string, DATE_FORMAT).date()
|
|
||||||
|
|
||||||
def handle_next_deployment_tag_command(self, args: argparse.Namespace):
|
|
||||||
next_deployment_tag = deployment_tag_for_date(args.date)
|
|
||||||
print(next_deployment_tag)
|
|
||||||
|
|
||||||
def deployment_tag_for_date(date: datetime.date) -> str:
|
|
||||||
formatted_date = date.strftime(DATE_FORMAT)
|
|
||||||
|
|
||||||
def deploy_tag_filter(tag):
|
|
||||||
return tag.startswith("deploy-") and formatted_date in tag
|
|
||||||
|
|
||||||
filtered_tags = sorted(filter(deploy_tag_filter, git_tags()))
|
|
||||||
|
|
||||||
if len(filtered_tags) == 0:
|
|
||||||
return f"deploy-{formatted_date}-01"
|
|
||||||
else:
|
|
||||||
last_tag = filtered_tags[-1]
|
|
||||||
components = last_tag.split("-")
|
|
||||||
if len(components) == 5:
|
|
||||||
# A previous numbered deployment. Add one to the last deployment
|
|
||||||
# number.
|
|
||||||
deployment_number = int(components[-1]) + 1
|
|
||||||
return f"deploy-{formatted_date}-{deployment_number:02}"
|
|
||||||
else:
|
|
||||||
# An old style deployment tag that doesn't have a number. There
|
|
||||||
# should only ever be one of these.
|
|
||||||
assert len(filtered_tags) == 1
|
|
||||||
return f"deploy-{formatted_date}-02"
|
|
||||||
|
|
||||||
|
|
||||||
def git_tags() -> List[str]:
|
|
||||||
return subprocess.check_output(
|
|
||||||
"git tag -l",
|
|
||||||
shell=True,
|
|
||||||
encoding="utf-8"
|
|
||||||
).splitlines()
|
|
||||||
|
|
@ -4,33 +4,16 @@
|
||||||
import os.path as osp
|
import os.path as osp
|
||||||
|
|
||||||
|
|
||||||
def root_dir() -> str:
|
|
||||||
'''Return the path to the root of the repository.'''
|
|
||||||
return osp.normpath(osp.join(osp.dirname(__file__), '..', '..'))
|
|
||||||
|
|
||||||
|
|
||||||
def assets_path() -> str:
|
|
||||||
'''Return the path to the assets directory.'''
|
|
||||||
path = osp.join(root_dir(), 'assets')
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def content_path() -> str:
|
def content_path() -> str:
|
||||||
'''Return the path to the content directory.'''
|
'''Return the path to the content directory.'''
|
||||||
path = osp.join(root_dir(), 'content')
|
path = osp.abspath(osp.join(osp.dirname(__file__), '..', '..', 'content'))
|
||||||
|
assert osp.isdir(path)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def blog_path() -> str:
|
def blog_path() -> str:
|
||||||
'''Return the path to the blog content directory.'''
|
|
||||||
return osp.join(content_path(), 'blog')
|
return osp.join(content_path(), 'blog')
|
||||||
|
|
||||||
|
|
||||||
def photos_path() -> str:
|
def photos_path() -> str:
|
||||||
'''Return the path to the photos content directory.'''
|
|
||||||
return osp.join(content_path(), 'photos')
|
return osp.join(content_path(), 'photos')
|
||||||
|
|
||||||
|
|
||||||
content_dir = content_path
|
|
||||||
blog_dir = blog_path
|
|
||||||
photos_dir = photos_path
|
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,5 @@ class Command:
|
||||||
def help(self) -> str:
|
def help(self) -> str:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def add_arguments(self, parser: argparse.ArgumentParser):
|
def add_arguments(self, _: argparse.ArgumentParser):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from .scripting import Command
|
||||||
|
|
||||||
class WeeknotesCommand(Command):
|
class WeeknotesCommand(Command):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def weeknotes_filename(year: str | int, week: str | int) -> str:
|
def weeknotes_filename(year: str, week: str) -> str:
|
||||||
return f'weeknotes-{year}w{week}.md'
|
return f'weeknotes-{year}w{week}.md'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -26,7 +26,7 @@ class WeeknotesCommand(Command):
|
||||||
week_number_str = next_sunday.strftime('%V')
|
week_number_str = next_sunday.strftime('%V')
|
||||||
|
|
||||||
return blog.post_path(WeeknotesCommand.weeknotes_filename(
|
return blog.post_path(WeeknotesCommand.weeknotes_filename(
|
||||||
year,
|
str(year),
|
||||||
week_number_str
|
week_number_str
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,23 +14,12 @@ from erynwells_me.metadata import slugify
|
||||||
from erynwells_me.paths import photos_path
|
from erynwells_me.paths import photos_path
|
||||||
|
|
||||||
|
|
||||||
def date_argument(value: str) -> datetime.datetime:
|
|
||||||
parsed_date = datetime.datetime.fromisoformat(value)
|
|
||||||
|
|
||||||
if not parsed_date.tzinfo:
|
|
||||||
local_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
|
|
||||||
parsed_date = datetime.datetime.combine(parsed_date.date(), parsed_date.time(), local_timezone)
|
|
||||||
|
|
||||||
return parsed_date
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args(argv, *a, **kw):
|
def parse_args(argv, *a, **kw):
|
||||||
parser = argparse.ArgumentParser(*a, **kw)
|
parser = argparse.ArgumentParser(*a, **kw)
|
||||||
parser.add_argument('-e', '--edit', action='store_true')
|
parser.add_argument('-e', '--edit', action='store_true')
|
||||||
parser.add_argument('-n', '--dry-run', action='store_true')
|
parser.add_argument('-n', '--dry-run', action='store_true')
|
||||||
parser.add_argument('-t', '--title')
|
parser.add_argument('-t', '--title')
|
||||||
parser.add_argument('-s', '--slug')
|
parser.add_argument('-s', '--slug')
|
||||||
parser.add_argument('-d', '--date', type=date_argument)
|
|
||||||
parser.add_argument('--dump-exif', action='store_true')
|
parser.add_argument('--dump-exif', action='store_true')
|
||||||
parser.add_argument('photos', nargs='+')
|
parser.add_argument('photos', nargs='+')
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
|
|
@ -40,7 +29,7 @@ def parse_args(argv, *a, **kw):
|
||||||
def main(argv):
|
def main(argv):
|
||||||
args = parse_args(argv[1:], prog=argv[0])
|
args = parse_args(argv[1:], prog=argv[0])
|
||||||
|
|
||||||
post_date: Optional[datetime.datetime] = args.date
|
earliest_exif_date: Optional[datetime.datetime] = None
|
||||||
|
|
||||||
for index, photo in enumerate(args.photos):
|
for index, photo in enumerate(args.photos):
|
||||||
print(f'image\t\t{photo}')
|
print(f'image\t\t{photo}')
|
||||||
|
|
@ -51,20 +40,14 @@ def main(argv):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
raw_exif = image._getexif()
|
raw_exif = image._getexif()
|
||||||
friendly_exif = {}
|
friendly_exif = {TAGS[k]: v for k, v in raw_exif.items() if k in TAGS}
|
||||||
if raw_exif:
|
|
||||||
friendly_exif = {TAGS[k]: v for k, v in raw_exif.items() if k in TAGS}
|
|
||||||
|
|
||||||
photo_date = None
|
try:
|
||||||
if not args.date:
|
date_string = f'{friendly_exif["DateTime"]} {friendly_exif["OffsetTime"]}'
|
||||||
try:
|
exif_date = datetime.datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S %z')
|
||||||
date_string = f'{friendly_exif["DateTime"]} {friendly_exif["OffsetTime"]}'
|
except KeyError:
|
||||||
photo_date = datetime.datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S %z')
|
exif_date = datetime.datetime.strptime(friendly_exif["DateTime"], '%Y:%m:%d %H:%M:%S')
|
||||||
except KeyError:
|
print(f'capture-time\t{exif_date.isoformat()}')
|
||||||
photo_date = datetime.datetime.strptime(friendly_exif["DateTime"], '%Y:%m:%d %H:%M:%S')
|
|
||||||
else:
|
|
||||||
photo_date = args.date
|
|
||||||
print(f'capture-time\t{photo_date.isoformat()}')
|
|
||||||
|
|
||||||
iso_rating = friendly_exif.get('ISOSpeedRatings')
|
iso_rating = friendly_exif.get('ISOSpeedRatings')
|
||||||
if iso_rating:
|
if iso_rating:
|
||||||
|
|
@ -83,24 +66,23 @@ def main(argv):
|
||||||
if exposure_time:
|
if exposure_time:
|
||||||
print(f'exposure-time\t{exposure_time}')
|
print(f'exposure-time\t{exposure_time}')
|
||||||
|
|
||||||
if not post_date or photo_date < post_date:
|
if not earliest_exif_date or exif_date < earliest_exif_date:
|
||||||
post_date = photo_date
|
earliest_exif_date = exif_date
|
||||||
|
|
||||||
if index < len(args.photos) - 1:
|
if index < len(args.photos) - 1:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if not post_date:
|
if not earliest_exif_date:
|
||||||
post_date = datetime.datetime.now()
|
earliest_exif_date = datetime.datetime.now()
|
||||||
|
|
||||||
year = post_date.year
|
year = earliest_exif_date.year
|
||||||
month = post_date.month
|
month = earliest_exif_date.month
|
||||||
|
|
||||||
if args.slug:
|
if args.slug:
|
||||||
name = args.slug
|
name = args.slug
|
||||||
elif args.title:
|
elif args.title:
|
||||||
name = slugify(args.title)
|
name = slugify(args.title)
|
||||||
else:
|
else:
|
||||||
photo = args.photos[0]
|
|
||||||
name = osp.splitext(osp.basename(photo))[0]
|
name = osp.splitext(osp.basename(photo))[0]
|
||||||
|
|
||||||
post_path_year = os.path.join(photos_path(), f'{year:04}', name)
|
post_path_year = os.path.join(photos_path(), f'{year:04}', name)
|
||||||
|
|
@ -118,7 +100,7 @@ def main(argv):
|
||||||
post_path = post_path_year
|
post_path = post_path_year
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hugo_command = ['hugo', 'new', '--clock', post_date.isoformat(), post_path]
|
hugo_command = ['hugo', 'new', '--clock', earliest_exif_date.isoformat(), post_path]
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
result = subprocess.run(hugo_command)
|
result = subprocess.run(hugo_command)
|
||||||
result.check_returncode()
|
result.check_returncode()
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,13 @@ A Python interface to my personal website, Erynwells.me.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
import os.path as osp
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from erynwells_me.scripting import Command
|
from erynwells_me.scripting import Command
|
||||||
from erynwells_me.weeknotes import WeeknotesCommand
|
from erynwells_me.weeknotes import WeeknotesCommand
|
||||||
from erynwells_me.deployment import DeploymentCommand
|
|
||||||
|
|
||||||
|
|
||||||
COMMANDS: List[Command] = [
|
COMMANDS: List[Command] = [
|
||||||
WeeknotesCommand(),
|
WeeknotesCommand(),
|
||||||
DeploymentCommand(),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,14 +29,7 @@ def parse_args(commands: List[Command], argv, *a, **kw):
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
program_name = osp.basename(argv[0])
|
args = parse_args(COMMANDS, argv[1:], prog=argv[0])
|
||||||
args = parse_args(COMMANDS, argv[1:], prog=program_name)
|
|
||||||
|
|
||||||
scripts_dir = osp.dirname(__file__)
|
|
||||||
repo_root_dir = osp.normpath(osp.join(scripts_dir, '..'))
|
|
||||||
if os.getcwd() != repo_root_dir:
|
|
||||||
os.chdir(repo_root_dir)
|
|
||||||
|
|
||||||
return args.handler(args)
|
return args.handler(args)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 89cde7aefb96525c09f51ea6318aa666b31f8a98
|
Subproject commit 4c101a552eb10ed87a5bec5bee741e65aa80daec
|
||||||
Loading…
Add table
Add a link
Reference in a new issue