Compare commits

..

No commits in common. "main" and "feeds" have entirely different histories.
main ... feeds

88 changed files with 2159 additions and 677 deletions

View file

@ -1,10 +1,18 @@
# Jessica OnLine 3.0
# JOL
This free ~~disc~~ repository entitles you to 10 **FREE** hours of Jessica OnLine!
To start your Phoenix server:
A blogthing that exists at [jess.canady.tech](https://jess.canady.tech).
* Run `mix setup` to install and setup dependencies
* Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
This is where I write about me. Writing software, playing games, cooking food, being a parent and a partner, and being a giant trans lesbian.
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
> Meet my one-eyed lesbian dad!
> --Alex, my eldest son and fiercest champio
Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
## Learn more
* Official website: https://www.phoenixframework.org/
* Guides: https://hexdocs.pm/phoenix/overview.html
* Docs: https://hexdocs.pm/phoenix
* Forum: https://elixirforum.com/c/phoenix-forum
* Source: https://github.com/phoenixframework/phoenix

18
TAGS.md
View file

@ -1,18 +0,0 @@
# JOL Taxonomy
Jessica OnLine endorses use of the following taxonomy categories:
* family
* games
* hardware
* howto
* shit's on fire yo
* software
* trans
* review
## Changelog
### 2024-08-25
Added initial list of tags.

View file

@ -1,5 +1,56 @@
.footer {
flex-grow: 0;
text-align: center;
opacity: 0.5;
}
.footer__inner {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
width: 760px;
max-width: 100%;
}
@media (max-width: 899px) {
.footer__inner {
flex-direction: column;
}
}
.footer a {
color: inherit;
}
.footer .copyright {
display: flex;
flex-direction: row;
align-items: center;
font-size: 1rem;
}
.footer .copyright--user {
margin: auto;
text-align: center;
}
.footer .copyright > *:first-child:not(:only-child) {
margin-right: 10px;
}
@media (max-width: 899px) {
.footer .copyright > *:first-child:not(:only-child) {
border: none;
padding: 0;
margin: 0;
}
}
@media (max-width: 899px) {
.footer .copyright {
flex-direction: column;
margin-top: 10px;
}
}
@media (max-width: 899px) {
.footer .copyright-theme-sep {
display: none;
}
}
@media (max-width: 899px) {
.footer .copyright-theme {
font-size: 0.75rem;
}
}

View file

@ -0,0 +1,83 @@
.button-container {
display: table;
margin-left: auto;
margin-right: auto; }
button,
.button,
a.button {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 8px 18px;
margin-bottom: 5px;
text-align: center;
border-radius: 8px;
border: 1px solid transparent;
appearance: none;
cursor: pointer;
outline: none;
/* variants */
/* sizes */ }
button.outline,
.button.outline,
a.button.outline {
background: transparent;
box-shadow: none;
padding: 8px 18px; }
button.outline :hover,
.button.outline :hover,
a.button.outline :hover {
transform: none;
box-shadow: none; }
button.primary,
.button.primary,
a.button.primary {
box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); }
button.primary:hover,
.button.primary:hover,
a.button.primary:hover {
box-shadow: 0 2px 6px rgba(50, 50, 93, 0.21), 0 1px 3px rgba(0, 0, 0, 0.08); }
button.link,
.button.link,
a.button.link {
background: none;
font-size: 1rem; }
button.small,
.button.small,
a.button.small {
font-size: .8rem; }
button.wide,
.button.wide,
a.button.wide {
min-width: 200px;
padding: 14px 24px; }
a.read-more,
a.read-more:hover,
a.read-more:active {
display: inline-flex;
background: none;
box-shadow: none;
padding: 0;
margin: 20px 0;
max-width: 100%; }
.code-toolbar {
margin-bottom: 20px; }
.code-toolbar .toolbar-item a {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 3px 8px;
margin-bottom: 5px;
text-align: center;
font-size: 13px;
font-weight: 500;
border-radius: 8px;
border: 1px solid transparent;
appearance: none;
cursor: pointer;
outline: none; }

View file

@ -0,0 +1,92 @@
.button-container {
display: table;
margin-left: auto;
margin-right: auto;
}
button,
.button,
a.button {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 8px 18px;
margin-bottom: 5px;
text-align: center;
border-radius: 8px;
border: 1px solid transparent;
appearance: none;
cursor: pointer;
outline: none;
/* variants */
&.outline {
background: transparent;
box-shadow: none;
padding: 8px 18px;
:hover {
transform: none;
box-shadow: none;
}
}
&.primary {
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
&:hover {
box-shadow: 0 2px 6px rgba(50, 50, 93, .21), 0 1px 3px rgba(0, 0, 0, .08);
}
}
&.link {
background: none;
font-size: 1rem;
}
/* sizes */
&.small {
font-size: .8rem;
}
&.wide {
min-width: 200px;
padding: 14px 24px;
}
}
a.read-more,
a.read-more:hover,
a.read-more:active {
display: inline-flex;
background: none;
box-shadow: none;
padding: 0;
margin: 20px 0;
max-width: 100%;
}
.code-toolbar {
margin-bottom: 20px;
.toolbar-item a {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 3px 8px;
margin-bottom: 5px;
text-align: center;
font-size: 13px;
font-weight: 500;
border-radius: 8px;
border: 1px solid transparent;
appearance: none;
cursor: pointer;
outline: none;
}
}

View file

@ -0,0 +1,14 @@
:root {
@media (prefers-color-scheme: light) {
--background: white;
--color: #101010;
}
@media (prefers-color-scheme: dark) {
--background: #101010;
--color: #A9B7C6;
}
}

View file

@ -0,0 +1,3 @@
:root {
--background: #1D212C;
}

View file

@ -0,0 +1,5 @@
:root {
--background: #101010;
--color: #A9B7C6;
}

View file

@ -0,0 +1,3 @@
:root {
--background: #1F222A;
}

View file

@ -0,0 +1,3 @@
:root {
--background: #f0f0f0;
}

View file

@ -0,0 +1,3 @@
:root {
--background: #222129;
}

View file

@ -0,0 +1,3 @@
:root {
--background: #21202C;
}

View file

@ -0,0 +1,3 @@
:root {
--background: #221F29;
}

View file

@ -0,0 +1,29 @@
:root {
@media (prefers-color-scheme: dark) {
--accent: rgb(35,176,255);
--accent-alpha-70: rgba(35,176,255,.7);
--accent-alpha-20: rgba(35,176,255,.2);
--background: #101010;
--color: #f0f0f0;
--border-color: rgba(255,240,224,.125);
div.logo {
color: black;
}
}
@media (prefers-color-scheme: light) {
--accent: rgb(32,128,192);
--accent-alpha-70: rgba(32,128,192,.7);
--accent-alpha-20: rgba(32,128,192,.2);
--background: white;
--color: #201030;
--border-color: rgba(0,0,16,.125);
div.logo {
color: white;
}
}
}

View file

@ -0,0 +1,12 @@
:root {
--accent: rgb(32,128,192);
--accent-alpha-70: rgba(32,128,192,.7);
--accent-alpha-20: rgba(32,128,192,.2);
--background: white;
--color: #1D212C;
--border-color: rgba(0, 0, 0, .1);
div.logo {
color: white;
}
}

View file

@ -0,0 +1,9 @@
:root {
--accent: rgb(35,176,255);
--accent-alpha-70: rgba(35,176,255,.7);
--accent-alpha-20: rgba(35,176,255,.2);
--background: #1D212C;
--color: white;
--border-color: rgba(255, 255, 255, .1);
}

View file

@ -0,0 +1,29 @@
:root {
@media (prefers-color-scheme: dark) {
--accent: rgb(120,226,160);
--accent-alpha-70: rgba(120,226,160,.7);
--accent-alpha-20: rgba(120,226,160,.2);
--background: #101010;
--color: #f0f0f0;
--border-color: rgba(255,240,224,.125);
div.logo {
color: black;
}
}
@media (prefers-color-scheme: light) {
--accent: rgb(24, 192, 128);
--accent-alpha-70: rgba(24, 192, 128,.7);
--accent-alpha-20: rgba(24, 192, 128,.2);
--background: white;
--color: #201030;
--border-color: rgba(0,0,16,.125);
div.logo {
color: white;
}
}
}

View file

@ -0,0 +1,12 @@
:root {
--accent: rgb(24, 192, 128);
--accent-alpha-70: rgba(24, 192, 128,.7);
--accent-alpha-20: rgba(24, 192, 128,.2);
--background: white;
--color: #1D212C;
--border-color: rgba(0, 0, 0, .1);
div.logo {
color: white;
}
}

View file

@ -0,0 +1,9 @@
:root {
--accent: rgb(120,226,160);
--accent-alpha-70: rgba(120,226,160,.7);
--accent-alpha-20: rgba(120,226,160,.2);
--background: #1F222A;
--color: white;
--border-color: rgba(255, 255, 255, .1);
}

View file

@ -0,0 +1,29 @@
:root {
@media (prefers-color-scheme: dark) {
--accent: rgb(255,168,106);
--accent-alpha-70: rgba(255,168,106,.7);
--accent-alpha-20: rgba(255,168,106,.2);
--background: #101010;
--color: #f0f0f0;
--border-color: rgba(255,240,224,.125);
div.logo {
color: black;
}
}
@media (prefers-color-scheme: light) {
--accent: rgb(240,128,48);
--accent-alpha-70: rgba(240,128,48,.7);
--accent-alpha-20: rgba(240,128,48,.2);
--background: white;
--color: #201030;
--border-color: rgba(0,0,16,.125);
div.logo {
color: white;
}
}
}

View file

@ -0,0 +1,12 @@
:root {
--accent: rgb(240,128,48);
--accent-alpha-70: rgba(240,128,48,.7);
--accent-alpha-20: rgba(240,128,48,.2);
--background: white;
--color: #1D212C;
--border-color: rgba(0, 0, 0, .1);
div.logo {
color: white;
}
}

View file

@ -0,0 +1,9 @@
:root {
--accent: rgb(255,168,106);
--accent-alpha-70: rgba(255,168,106,.7);
--accent-alpha-20: rgba(255,168,106,.2);
--background: #222129;
--color: white;
--border-color: rgba(255, 255, 255, .1);
}

View file

@ -0,0 +1,29 @@
:root {
@media (prefers-color-scheme: dark) {
--accent: rgb(224,64,192);
--accent-alpha-70: rgba(224,64,192);
--accent-alpha-20: rgba(224,64,192,.2);
--background: #101010;
--color: #f0f0f0;
--border-color: rgba(255,240,224,.125);
div.logo {
color: black;
}
}
@media (prefers-color-scheme: light) {
--accent: rgb(238,114,241);
--accent-alpha-70: rgba(238,114,241,.7);
--accent-alpha-20: rgba(238,114,241,.2);
--background: white;
--color: #201030;
--border-color: rgba(0,0,16,.125);
div.logo {
color: white;
}
}
}

View file

@ -0,0 +1,12 @@
:root {
--accent: rgb(224,64,192);
--accent-alpha-70: rgba(224,64,192);
--accent-alpha-20: rgba(224,64,192,.2);
--background: white;
--color: #1D212C;
--border-color: rgba(0, 0, 0, .1);
div.logo {
color: white;
}
}

View file

@ -0,0 +1,9 @@
:root {
--accent: rgb(238,114,241);
--accent-alpha-70: rgba(238,114,241,.7);
--accent-alpha-20: rgba(238,114,241,.2);
--background: #21202C;
--color: white;
--border-color: rgba(255, 255, 255, .1);
}

View file

@ -0,0 +1,29 @@
:root {
@media (prefers-color-scheme: dark) {
--accent: rgb(255,98,102);
--accent-alpha-70: rgba(255,98,102,.7);
--accent-alpha-20: rgba(255,98,102,.2);
--background: #101010;
--color: #f0f0f0;
--border-color: rgba(255,240,224,.125);
div.logo {
color: black;
}
}
@media (prefers-color-scheme: light) {
--accent: rgb(240,48,64);
--accent-alpha-70: rgba(240,48,64,.7);
--accent-alpha-20: rgba(240,48,64,.2);
--background: white;
--color: #201030;
--border-color: rgba(0,0,16,.125);
div.logo {
color: white;
}
}
}

View file

@ -0,0 +1,12 @@
:root {
--accent: rgb(240,48,64);
--accent-alpha-70: rgba(240,48,64,.7);
--accent-alpha-20: rgba(240,48,64,.2);
--background: white;
--color: #1D212C;
--border-color: rgba(0, 0, 0, .1);
div.logo {
color: white;
}
}

View file

@ -0,0 +1,9 @@
:root {
--accent: rgb(255,98,102);
--accent-alpha-70: rgba(255,98,102,.7);
--accent-alpha-20: rgba(255,98,102,.2);
--background: #221F29;
--color: white;
--border-color: rgba(255, 255, 255, .1);
}

View file

@ -0,0 +1,27 @@
/*!
* Hack typeface https://github.com/source-foundry/Hack
* License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md
*/
/* FONT PATHS
* -------------------------- */
@font-face {
font-family: 'Hack';
/* Use full version (not a subset) for unicode icon support */
src: url("fonts/hack-regular.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-regular.woff?sha=3114f1256") format("woff");
font-weight: 400;
font-style: normal; }
@font-face {
font-family: 'Hack';
src: url("fonts/hack-bold-subset.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-bold-subset.woff?sha=3114f1256") format("woff");
font-weight: 700;
font-style: normal; }
@font-face {
font-family: 'Hack';
src: url("fonts/hack-italic-subset.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-italic-webfont.woff?sha=3114f1256") format("woff");
font-weight: 400;
font-style: italic; }
@font-face {
font-family: 'Hack';
src: url("fonts/hack-bolditalic-subset.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-bolditalic-subset.woff?sha=3114f1256") format("woff");
font-weight: 700;
font-style: italic; }

View file

@ -0,0 +1,34 @@
/*!
* Hack typeface https://github.com/source-foundry/Hack
* License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md
*/
/* FONT PATHS
* -------------------------- */
@font-face {
font-family: 'Hack';
/* Use full version (not a subset) for unicode icon support */
src: url('fonts/hack-regular.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-regular.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-bold-subset.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-bold-subset.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-italic-subset.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-italic-webfont.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-bolditalic-subset.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-bolditalic-subset.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: italic;
}

View file

@ -0,0 +1,26 @@
/*!
* Hack typeface https://github.com/source-foundry/Hack
* License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md
*/
/* FONT PATHS
* -------------------------- */
@font-face {
font-family: 'Hack';
src: url("fonts/hack-regular.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-regular.woff?sha=3114f1256") format("woff");
font-weight: 400;
font-style: normal; }
@font-face {
font-family: 'Hack';
src: url("fonts/hack-bold.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-bold.woff?sha=3114f1256") format("woff");
font-weight: 700;
font-style: normal; }
@font-face {
font-family: 'Hack';
src: url("fonts/hack-italic.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-italic.woff?sha=3114f1256") format("woff");
font-weight: 400;
font-style: italic; }
@font-face {
font-family: 'Hack';
src: url("fonts/hack-bolditalic.woff2?sha=3114f1256") format("woff2"), url("fonts/hack-bolditalic.woff?sha=3114f1256") format("woff");
font-weight: 700;
font-style: italic; }

View file

@ -0,0 +1,33 @@
/*!
* Hack typeface https://github.com/source-foundry/Hack
* License: https://github.com/source-foundry/Hack/blob/master/LICENSE.md
*/
/* FONT PATHS
* -------------------------- */
@font-face {
font-family: 'Hack';
src: url('fonts/hack-regular.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-regular.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-bold.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-bold.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-italic.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-italic.woff?sha=3114f1256') format('woff');
font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'Hack';
src: url('fonts/hack-bolditalic.woff2?sha=3114f1256') format('woff2'), url('fonts/hack-bolditalic.woff?sha=3114f1256') format('woff');
font-weight: 700;
font-style: italic;
}

View file

@ -0,0 +1,40 @@
.footer {
flex-grow: 0;
opacity: .5; }
.footer__inner {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
width: 760px;
max-width: 100%; }
@media (max-width: 899px) {
.footer__inner {
flex-direction: column; } }
.footer a {
color: inherit; }
.footer .copyright {
display: flex;
flex-direction: row;
align-items: center;
font-size: 1rem; }
.footer .copyright--user {
margin: auto;
text-align: center; }
.footer .copyright > *:first-child:not(:only-child) {
margin-right: 10px; }
@media (max-width: 899px) {
.footer .copyright > *:first-child:not(:only-child) {
border: none;
padding: 0;
margin: 0; } }
@media (max-width: 899px) {
.footer .copyright {
flex-direction: column;
margin-top: 10px; } }
@media (max-width: 899px) {
.footer .copyright-theme-sep {
display: none; } }
@media (max-width: 899px) {
.footer .copyright-theme {
font-size: 0.75rem; } }

View file

@ -0,0 +1,62 @@
@import "variables";
.footer {
flex-grow: 0;
opacity: .5;
&__inner {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
width: 760px;
max-width: 100%;
@media (max-width: $tablet-max-width) {
flex-direction: column;
}
}
a {
color: inherit;
}
.copyright {
display: flex;
flex-direction: row;
align-items: center;
font-size: 1rem;
&--user {
margin: auto;
text-align: center;
}
& > *:first-child:not(:only-child) {
margin-right: 10px;
@media (max-width: $tablet-max-width) {
border: none;
padding: 0;
margin: 0;
}
}
@media (max-width: $tablet-max-width) {
flex-direction: column;
margin-top: 10px;
}
}
.copyright-theme-sep {
@media (max-width: $tablet-max-width) {
display: none;
}
}
.copyright-theme {
@media (max-width: $tablet-max-width) {
font-size: 0.75rem;
}
}
}

View file

@ -0,0 +1,61 @@
.header {
display: flex;
flex-direction: column;
position: relative; }
.header__inner {
display: flex;
align-items: center;
justify-content: space-between; }
.header__logo {
display: flex;
flex: 1; }
.header__logo:after {
content: '';
background: repeating-linear-gradient(90deg, var(--accent), var(--accent) 2px, transparent 0, transparent 16px);
display: block;
width: 100%;
right: 10px; }
.header__logo a {
flex: 0 0 auto;
max-width: 100%; }
.header .menu {
margin: 20px 0; }
.header .menu__inner {
display: flex;
flex-wrap: wrap;
list-style: none;
margin: 0;
padding: 0; }
.header .menu__inner li.active {
color: var(--accent-alpha-70); }
.header .menu__inner li:not(:last-of-type) {
margin-right: 20px;
margin-bottom: 10px;
flex: 0 0 auto; }
.header .menu__sub-inner {
position: relative;
list-style: none;
padding: 0;
margin: 0; }
.header .menu__sub-inner:not(:only-child) {
margin-left: 20px; }
.header .menu__sub-inner-more {
position: absolute;
background: var(--background);
box-shadow: var(--shadow);
color: white;
border: 2px solid;
margin: 0;
padding: 10px;
list-style: none;
z-index: 99;
top: 35px;
left: 0; }
.header .menu__sub-inner-more-trigger {
color: var(--accent);
user-select: none;
cursor: pointer; }
.header .menu__sub-inner-more li {
margin: 0;
padding: 5px;
white-space: nowrap; }

View file

@ -0,0 +1,96 @@
@import "variables";
@mixin menu {
position: absolute;
background: var(--background);
box-shadow: var(--shadow);
color: white;
border: 2px solid;
margin: 0;
padding: 10px;
list-style: none;
z-index: 99;
}
.header {
display: flex;
flex-direction: column;
position: relative;
&__inner {
display: flex;
align-items: center;
justify-content: space-between;
}
&__logo {
display: flex;
flex: 1;
&:after {
content: '';
background: repeating-linear-gradient(90deg, var(--accent), var(--accent) 2px, transparent 0, transparent 16px);
display: block;
width: 100%;
right: 10px;
}
a {
flex: 0 0 auto;
max-width: 100%;
}
}
.menu {
margin: 20px 0;
&__inner {
display: flex;
flex-wrap: wrap;
list-style: none;
margin: 0;
padding: 0;
li {
&.active {
color: var(--accent-alpha-70);
}
&:not(:last-of-type) {
margin-right: 20px;
margin-bottom: 10px;
flex: 0 0 auto;
}
}
}
&__sub-inner {
position: relative;
list-style: none;
padding: 0;
margin: 0;
&:not(:only-child) {
margin-left: 20px;
}
&-more {
@include menu;
top: 35px;
left: 0;
&-trigger {
color: var(--accent);
user-select: none;
cursor: pointer;
}
li {
margin: 0;
padding: 5px;
white-space: nowrap;
}
}
}
}
}

4
assets/css/sass/home.css Normal file
View file

@ -0,0 +1,4 @@
div.homepage {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
grid-gap: 3em; }

View file

@ -0,0 +1,5 @@
div.homepage {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
grid-gap: 3em;
}

7
assets/css/sass/logo.css Normal file
View file

@ -0,0 +1,7 @@
.logo {
display: flex;
align-items: center;
text-decoration: none;
background: var(--accent);
color: black;
padding: 5px 10px; }

View file

@ -0,0 +1,8 @@
.logo {
display: flex;
align-items: center;
text-decoration: none;
background: var(--accent);
color: black;
padding: 5px 10px;
}

66
assets/css/sass/main.css Normal file
View file

@ -0,0 +1,66 @@
/*
Error: wrong number of arguments (1 for 3) for `rgb'
on line 242 of main.scss
237: padding: 40px;
238: max-width: 864px;
239: // min-height: 100vh;
240: margin: 2em auto;
241:
242: background: rgb(0 0 0 / .4);
243:
244: @media (max-width: $phone-max-width) {
245: padding: 20px;
246: margin: 0 auto;
247: }
Backtrace:
main.scss:242
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/funcall.rb:311:in `reformat_argument_error'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/funcall.rb:158:in `rescue in _perform'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/funcall.rb:127:in `_perform'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/node.rb:50:in `perform'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:398:in `visit_prop'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `block in with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:135:in `with_frame'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:440:in `block (2 levels) in visit_rule'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:440:in `map'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:440:in `block in visit_rule'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:438:in `visit_rule'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `block in with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:135:in `with_frame'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:52:in `block in visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:52:in `map'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:52:in `visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:167:in `block in visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:166:in `visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:186:in `visit_root'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:157:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:10:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/root_node.rb:36:in `css_tree'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/root_node.rb:20:in `render'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/engine.rb:290:in `render'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/sass_scss.rb:396:in `run'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/sass_scss.rb:63:in `process_result'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/base.rb:50:in `parse'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/base.rb:18:in `parse!'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/bin/sass:13:in `<top (required)>'
/home/jess/.asdf/installs/ruby/3.3.0/bin/sass:25:in `load'
/home/jess/.asdf/installs/ruby/3.3.0/bin/sass:25:in `<main>'
*/
body:before {
white-space: pre;
font-family: monospace;
content: "Error: wrong number of arguments (1 for 3) for `rgb'\A on line 242 of main.scss\A \A 237: padding: 40px;\A 238: max-width: 864px;\A 239: // min-height: 100vh;\A 240: margin: 2em auto;\A 241: \A 242: background: rgb(0 0 0 / .4);\A 243: \A 244: @media (max-width: $phone-max-width) {\A 245: padding: 20px;\A 246: margin: 0 auto;\A 247: }"; }

263
assets/css/sass/main.scss Normal file
View file

@ -0,0 +1,263 @@
@import "variables";
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
font-family: Hack, DejaVu Sans Mono, Monaco, Consolas, Ubuntu Mono, monospace;
font-size: 1rem;
line-height: 1.54;
// background-color: var(--background);
color: var(--color);
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-text-size-adjust: 100%;
@media (max-width: $phone-max-width) {
font-size: 1rem;
}
}
.bg {
background: radial-gradient(at right top, #F68EF0, #74B9DF);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-height: 100vh;
min-height: 100dvh;
z-index: -1;
}
h1, h2, h3, h4, h5, h6 {
display: flex;
align-items: center;
font-weight: bold;
line-height: 1.3;
}
h1 {
font-size: 1.4rem;
}
h2 {
font-size: 1.3rem;
}
h3 {
font-size: 1.2rem;
}
h4, h5, h6 {
font-size: 1.15rem;
}
a {
color: inherit;
}
img {
display: block;
max-width: 100%;
&.left {
margin-right: auto;
}
&.center {
margin-left: auto;
margin-right: auto;
}
&.right {
margin-left: auto;
}
}
p {
margin-bottom: 20px;
}
figure {
display: table;
max-width: 100%;
margin: 25px 0;
&.left, img {
margin-right: auto;
}
&.center, img {
margin-left: auto;
margin-right: auto;
}
&.right, img {
margin-left: auto;
}
figcaption {
font-size: 14px;
padding: 5px 10px;
margin-top: 5px;
background: var(--accent);
color: var(--background);
&.left {
text-align: left;
}
&.center {
text-align: center;
}
&.right {
text-align: right;
}
}
}
code {
font-family: Hack, DejaVu Sans Mono, Monaco, Consolas, Ubuntu Mono, monospace;
font-feature-settings: normal;
background: var(--accent-alpha-20);
padding: 1px 6px;
margin: 0 2px;
font-size: .95rem;
}
pre {
font-family: Hack, DejaVu Sans Mono, Monaco, Consolas, Ubuntu Mono, monospace;
padding: 20px;
font-size: .95rem;
overflow: auto;
border-top: 1px solid rgba(255, 255, 255, .1);
border-bottom: 1px solid rgba(255, 255, 255, .1);
@media (max-width: $phone-max-width) {
white-space: pre-wrap;
word-wrap: break-word;
}
code {
padding: 0;
margin: 0;
background: none;
}
}
blockquote {
border-top: 1px solid var(--accent);
border-bottom: 1px solid var(--accent);
margin: 40px 0;
padding: 25px;
@media (max-width: $phone-max-width) {
padding-right: 0;
}
&:before {
content: '';
font-family: Georgia, serif;
font-size: 3.875rem;
position: absolute;
left: -40px;
top: -20px;
}
p:first-of-type {
margin-top: 0;
}
p:last-of-type {
margin-bottom: 0;
}
p {
position: relative;
}
p:before {
content: '>';
display: block;
position: absolute;
left: -25px;
color: var(--accent);
}
}
table {
table-layout: fixed;
border-collapse: collapse;
width: 100%;
margin: 40px 0;
}
table, th, td {
border: 1px dashed var(--accent);
padding: 10px;
}
th {
color: var(--accent);
}
ul, ol {
margin-left: 30px;
padding: 0;
li {
position: relative;
}
@media (max-width: $phone-max-width) {
margin-left: 20px;
}
}
ol ol {
list-style-type: lower-alpha;
}
.container {
display: flex;
flex-direction: column;
padding: 40px;
max-width: 864px;
// min-height: 100vh;
margin: 2em auto;
background: rgb(0 0 0 / .4);
@media (max-width: $phone-max-width) {
padding: 20px;
margin: 0 auto;
}
}
.content {
display: flex;
}
hr {
width: 100%;
border: none;
background: var(--border-color);
height: 1px;
}
.hidden {
display: none;
}

View file

@ -0,0 +1,57 @@
.pagination {
margin-top: 50px; }
.pagination__title {
display: flex;
text-align: center;
position: relative;
margin: 100px 0 20px; }
.pagination__title-h {
text-align: center;
margin: 0 auto;
padding: 5px 10px;
background: var(--background);
font-size: .8rem;
text-transform: uppercase;
letter-spacing: .1em;
z-index: 1; }
.pagination__title hr {
position: absolute;
left: 0;
right: 0;
width: 100%;
margin-top: 15px;
z-index: 0; }
.pagination__buttons {
display: flex;
align-items: center;
justify-content: center; }
@media (max-width: 683px) {
.pagination__buttons {
flex-direction: column; } }
.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1rem;
border-radius: 8px;
max-width: 40%;
padding: 0;
cursor: pointer;
appearance: none; }
@media (max-width: 683px) {
.button {
max-width: 80%; } }
.button + .button {
margin-left: 10px; }
.button a {
display: flex;
padding: 8px 16px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden; }
.button__text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden; }

View file

@ -0,0 +1,77 @@
@import 'variables';
.pagination {
margin-top: 50px;
&__title {
display: flex;
text-align: center;
position: relative;
margin: 100px 0 20px;
&-h {
text-align: center;
margin: 0 auto;
padding: 5px 10px;
background: var(--background);
font-size: .8rem;
text-transform: uppercase;
letter-spacing: .1em;
z-index: 1;
}
hr {
position: absolute;
left: 0;
right: 0;
width: 100%;
margin-top: 15px;
z-index: 0;
}
}
&__buttons {
display: flex;
align-items: center;
justify-content: center;
@media (max-width: $phone-max-width) {
flex-direction: column;
}
}
}
.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1rem;
border-radius: 8px;
max-width: 40%;
padding: 0;
cursor: pointer;
appearance: none;
@media (max-width: $phone-max-width) {
max-width: 80%;
}
+ .button {
margin-left: 10px;
}
a {
display: flex;
padding: 8px 16px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
&__text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}

79
assets/css/sass/post.css Normal file
View file

@ -0,0 +1,79 @@
@charset "UTF-8";
.posts {
width: 100%;
margin: 0 auto; }
.post {
width: 100%;
text-align: left;
margin: 20px auto;
padding: 20px 0; }
@media (max-width: 899px) {
.post {
max-width: 660px; } }
.post:not(:last-of-type) {
border-bottom: 1px solid var(--border-color); }
.post .post-meta, .post .post-meta-inline {
font-size: 1rem;
margin-bottom: 10px;
color: var(--accent-alpha-70); }
.post-meta-inline {
display: inline; }
.post-title {
--border: 2px dashed var(--accent);
position: relative;
color: var(--accent);
margin: 0 0 15px;
padding-bottom: 15px;
border-bottom: var(--border);
font-weight: normal; }
.post-title a {
text-decoration: none; }
.post .post-tags, .post .post-tags-inline {
margin-bottom: 20px;
font-size: 1rem;
opacity: .5; }
.post-tags {
display: block; }
.post-tags-inline {
display: inline; }
@media (max-width: 683px) {
.post-tags-inline {
display: block; } }
.post-content {
margin-top: 30px; }
.post-cover {
border: 20px solid var(--accent);
background: transparent;
margin: 40px 0;
padding: 20px; }
@media (max-width: 683px) {
.post-cover {
padding: 10px;
border-width: 10px; } }
.post ul {
list-style: none; }
.post ul li:before {
content: '►';
position: absolute;
left: -20px;
color: var(--accent); }
.post--regulation h1 {
justify-content: center; }
.post--regulation h2 {
justify-content: center;
margin-bottom: 10px; }
.post--regulation h2 + h2 {
margin-top: -10px;
margin-bottom: 20px; }
.post-list .post-date {
color: var(--accent);
text-decoration: none; }
.post-list a {
text-decoration: none; }
.post-list .post-list-title {
text-decoration: underline; }
.post-list .post-tag {
text-decoration: underline; }

135
assets/css/sass/post.scss Normal file
View file

@ -0,0 +1,135 @@
@import "variables";
.posts {
width: 100%;
margin: 0 auto;
}
.post {
width: 100%;
text-align: left;
margin: 20px auto;
padding: 20px 0;
@media (max-width: $tablet-max-width) {
max-width: 660px;
}
&:not(:last-of-type) {
border-bottom: 1px solid var(--border-color);
}
%meta {
font-size: 1rem;
margin-bottom: 10px;
color: var(--accent-alpha-70);
}
&-meta {
@extend %meta;
}
&-meta-inline {
@extend %meta;
display: inline;
}
&-title {
--border: 2px dashed var(--accent);
position: relative;
color: var(--accent);
margin: 0 0 15px;
padding-bottom: 15px;
border-bottom: var(--border);
font-weight: normal;
a {
text-decoration: none;
}
}
%tags {
margin-bottom: 20px;
font-size: 1rem;
opacity: .5;
}
&-tags {
@extend %tags;
display: block;
}
&-tags-inline {
@extend %tags;
display: inline;
@media (max-width: $phone-max-width) {
display: block;
}
}
&-content {
margin-top: 30px;
}
&-cover {
border: 20px solid var(--accent);
background: transparent;
margin: 40px 0;
padding: 20px;
@media (max-width: $phone-max-width) {
padding: 10px;
border-width: 10px;
}
}
ul {
list-style: none;
li:before {
content: '';
position: absolute;
left: -20px;
color: var(--accent);
}
}
}
.post--regulation {
h1 {
justify-content: center;
}
h2 {
justify-content: center;
margin-bottom: 10px;
&+ h2 {
margin-top: -10px;
margin-bottom: 20px;
}
}
}
.post-list {
.post-date {
color: var(--accent);
text-decoration: none;
}
a {
text-decoration: none;
}
.post-list-title {
text-decoration: underline;
}
.post-tag {
text-decoration: underline;
}
}

69
assets/css/sass/style.css Normal file
View file

@ -0,0 +1,69 @@
/*
Error: wrong number of arguments (1 for 3) for `rgb'
on line 242 of main.scss
from line 5 of style.scss
Backtrace:
main.scss:242
style.scss:5
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/funcall.rb:311:in `reformat_argument_error'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/funcall.rb:158:in `rescue in _perform'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/funcall.rb:127:in `_perform'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/script/tree/node.rb:50:in `perform'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:398:in `visit_prop'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `block in with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:135:in `with_frame'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:440:in `block (2 levels) in visit_rule'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:440:in `map'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:440:in `block in visit_rule'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:438:in `visit_rule'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `block in with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:135:in `with_frame'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:325:in `block (2 levels) in visit_import'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:325:in `map'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:325:in `block in visit_import'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:88:in `block in with_import'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:135:in `with_frame'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:88:in `with_import'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:322:in `visit_import'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `block in with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:135:in `with_frame'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/stack.rb:79:in `with_base'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:158:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:52:in `block in visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:52:in `map'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:52:in `visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:167:in `block in visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:166:in `visit_children'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `block in visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:186:in `visit_root'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/base.rb:36:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:157:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/visitors/perform.rb:10:in `visit'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/root_node.rb:36:in `css_tree'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/tree/root_node.rb:20:in `render'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/engine.rb:290:in `render'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/sass_scss.rb:396:in `run'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/sass_scss.rb:63:in `process_result'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/base.rb:50:in `parse'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/lib/sass/exec/base.rb:18:in `parse!'
/home/jess/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/sass-3.7.4/bin/sass:13:in `<top (required)>'
/home/jess/.asdf/installs/ruby/3.3.0/bin/sass:25:in `load'
/home/jess/.asdf/installs/ruby/3.3.0/bin/sass:25:in `<main>'
*/
body:before {
white-space: pre;
font-family: monospace;
content: "Error: wrong number of arguments (1 for 3) for `rgb'\A on line 242 of main.scss\A from line 5 of style.scss"; }

View file

@ -0,0 +1,9 @@
@import 'buttons';
@import 'header';
@import 'logo';
@import 'main';
@import 'post';
@import 'pagination';
@import 'footer';
@import 'home';

View file

View file

@ -0,0 +1,2 @@
$phone-max-width: 683px;
$tablet-max-width: 899px;

View file

@ -1,10 +1,4 @@
@charset "UTF-8";
@import "./footer.css";
@font-face {
font-family: "BerkeleyMono";
src: url("/fonts/BerkeleyMonoVariable-Regular.woff2") format("woff2");
}
.button-container {
display: table;
@ -211,7 +205,7 @@ body {
margin: 0;
padding: 0;
font-family:
BerkeleyMono,
Hack,
DejaVu Sans Mono,
Monaco,
Consolas,
@ -333,7 +327,7 @@ figure figcaption.right {
code {
font-family:
BerkeleyMono,
Hack,
DejaVu Sans Mono,
Monaco,
Consolas,
@ -348,7 +342,7 @@ code {
pre {
font-family:
BerkeleyMono,
Hack,
DejaVu Sans Mono,
Monaco,
Consolas,
@ -434,7 +428,6 @@ ol {
ul li,
ol li {
position: relative;
margin-top: 0.5rem;
}
@media (max-width: 683px) {
ul,
@ -656,6 +649,63 @@ hr {
overflow: hidden;
}
.footer {
flex-grow: 0;
opacity: 0.5;
}
.footer__inner {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
width: 760px;
max-width: 100%;
}
@media (max-width: 899px) {
.footer__inner {
flex-direction: column;
}
}
.footer a {
color: inherit;
}
.footer .copyright {
display: flex;
flex-direction: row;
align-items: center;
font-size: 1rem;
}
.footer .copyright--user {
margin: auto;
text-align: center;
}
.footer .copyright > *:first-child:not(:only-child) {
margin-right: 10px;
}
@media (max-width: 899px) {
.footer .copyright > *:first-child:not(:only-child) {
border: none;
padding: 0;
margin: 0;
}
}
@media (max-width: 899px) {
.footer .copyright {
flex-direction: column;
margin-top: 10px;
}
}
@media (max-width: 899px) {
.footer .copyright-theme-sep {
display: none;
}
}
@media (max-width: 899px) {
.footer .copyright-theme {
font-size: 0.75rem;
}
}
div.homepage {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
@ -672,7 +722,3 @@ div.post_summary {
margin-bottom: 1em;
padding: 0.5rem;
}
ul.recent-posts li {
margin-top: 1rem;
}

View file

@ -7,8 +7,6 @@
# General application configuration
import Config
config :elixir, :time_zone_database, Tz.TimeZoneDatabase
config :jol,
namespace: JOL,
ecto_repos: [JOL.Repo],

View file

@ -13,21 +13,17 @@ kill_signal = 'SIGTERM'
release_command = '/app/bin/migrate'
[env]
PHX_HOST = 'jess.canady.tech'
PHX_HOST = 'jol.fly.dev'
PORT = '8080'
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = "stop"
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ['app']
[[http_service.checks]]
timeout = "30s"
grace_period = "30s"
[http_service.concurrency]
type = 'connections'
hard_limit = 1000

View file

@ -44,8 +44,4 @@ defmodule JOL.Blog do
posts -> posts
end
end
def format_date(date) do
Calendar.strftime(date, "%Y-%m-%d")
end
end

View file

@ -33,8 +33,11 @@
</div>
<footer class="footer">
<div class="footer__inner">
<div class="copyright copyright--user">
<a href={~p"/colophon/"}>Built with</a> trans dork love.
Built with trans dork love.
</div>
</div>
</footer>
</div>

View file

@ -4,11 +4,10 @@ defmodule JOLWeb.BlogController do
alias JOL.Blog
def index(conn, _params) do
render(conn, "index.html", page_title: "You Asked For Posts", posts: Blog.recent_posts())
render(conn, "index.html", posts: Blog.recent_posts())
end
def show(conn, %{"slug" => slug}) do
post = Blog.get_post_by_slug!(slug)
render(conn, "show.html", page_title: post.title, post: post)
render(conn, "show.html", post: Blog.get_post_by_slug!(slug))
end
end

View file

@ -2,7 +2,7 @@
<%= for post <- @posts do %>
<div class="post-summary">
<p class="post-date"><date><%= JOL.Blog.format_date(post.date) %></date></p>
<p class="post-date"><date><%= post.date %></date></p>
<h3> <.link href={~p"/blog/#{post.slug}"}><%= post.title %> </.link> </h3>
<p><%= raw post.lede %></p>
</div>

View file

@ -3,11 +3,11 @@
<h1><%= @post.title %></h1>
<p>
<date><%= JOL.Blog.format_date(@post.date) %></date>
<time><%= @post.date %></time> by <%= @post.author %>
</p>
<p>
Tagged as <%= Enum.join(@post.tags, ", ") %>
</p>
<%= raw @post.body %>
<p class="post-tags">
Filed under: <%= Enum.join(@post.tags, ", ") %>
</p>

View file

@ -4,21 +4,27 @@ defmodule JOLWeb.PageController do
@spec home(Plug.Conn.t(), any()) :: Plug.Conn.t()
def home(conn, _params) do
conn
|> render(:home, page_title: "Welcome!", posts: JOL.Blog.recent_posts())
|> assign(:page_title, "Home")
|> render(:home)
end
@spec tags(Plug.Conn.t(), any()) :: Plug.Conn.t()
def tags(conn, _params) do
conn
|> assign(:tags, JOL.Blog.unique_tag_list())
|> assign(:page_title, "Post Tags")
|> render(:tags)
end
def about(conn, _params) do
conn
|> render(:about, page_title: "The Life and Times of Jessica Phoenix Canady")
|> assign(:page_title, "About Jessica")
|> render(:about)
end
def now(conn, _params) do
conn
|> render(:now, page_title: "Current Status")
end
def colophon(conn, _params) do
conn
|> render(:colophon, page_title: "about:jol")
|> assign(:page_title, "Current Status")
|> render(:now)
end
end

View file

@ -1,25 +1,3 @@
<h1 class="post-title">About Jessica</h1>
<p>I'm <strong>Jessica Phoenix Canady</strong>, a web development dork who lives in Columbus Ohio with her wife, two boys, and two cats.</p>
<p>I write web software (mostly in Elixir and Ruby), dork around with server infrastructure and security, and play music on keys and synths. I also play the occasional video game and hand of poker.</p>
<p>For eleven years of my earlier life I built CoverMyMeds, from inception to acquisition in 2017. I was responsible for much of the early dev culture and processes, as well as the backend that manages sending faxes; the backend for the electronic prior auth systems, the PA workflow software <em>Central</em>, and a ton more I can no longer recall.</p>
<h2 id="selected-histories">Selected Histories</h2>
<h3 id="chapter-onestumbled-into-life">Chapter One<br>Stumbled Into Life</h3>
<ul>
<li>Webmistress'd and wrote copy for several websites (including Comic Town's, see below) back when the Web was wild and new and I was young <del>and brave</del>.</li>
<li>Matriculated at the world-renowned DeVry University (<em>cough</em>) and graduated just as the first dot-com bubble burst.</li>
<li>Clerked at a comic book store, the glorious Comic Town in Columbus OH, when it was at its various Morse Rd locations. Pour one out for a real one. <strong>RIP Comic Town, 199x-2023.</strong> </li>
</ul>
<h3 id="chapter-2she-thinks-she-s-grown-up">Chapter 2<br>She Thinks She's Grown Up</h3>
<ul>
<li>After finding their help wanted ad on Craigslist, annoyed the dorks at Innova Partners until they gave me a job as a developer at their consultancy. They lured me with the promise of free lunch every day.</li>
<li>❤️ Got married to my high school sweetheart and best friend, Kelli. ❤️</li>
<li>Ran the Columbus Ruby Brigade (as a volunteer emcee, a board member, and President of the board) for some years, running their meetings and booking speakers. </li>
<li>Had two children, Alex and Quentin. I thought I knew what love was, then I laid eyes on my babies, and I realized I had no idea until that moment. Funnily enough this happened with both kids, four years apart.</li>
<li>Helped Innova write a ton of software for a project called CoverMyMeds. This turned into a product that we turned into a company that, in 2017, got bought by McKesson for one-point-four billion dollars.</li>
</ul>
<h3 id="chapter-3the-light-inside-is-burnt-out-but-she-still-works">Chapter 3<br>The Light Inside is Burnt Out but She Still Works</h3>
<ul>
<li>Began transitioning my gender, which has been the best thing I've ever done for my mental health.</li>
<li>As their VP of Engineering, spent two years building the tech and team at <a href="https://prescribefit.com">Prescribe FIT</a> here in Columbus OH. I left that position in early 2023, now I'm just an investor.</li>
</ul>
More to come.

View file

@ -1,27 +0,0 @@
<h1 class="post-title">about:jol</h1>
<h2>The Software</h2>
<p>
Jessica OnLine is pwoered by a <a href="https://forge.sigill.zone/phoenix/jol/">custom Elixir/Phoenix application</a>. Feel free to look through the implementation and take what makes sense for you -- not all of it will even be <em>good</em>, let alone correct for what you want to do, but hopefully it's helpful.
</p>
<p>
The point of the app is to find the sweet spot between "easy to update but overly complex to manage and style" Wordpress, and "Markup rules until I have to upload images" static site generators.
</p>
<h2>The Editor</h2>
<p>
Mostly written in <a href="https://www.gnu.org/software/emacs/">Emacs</a> with the <a href="https://github.com/doomemacs/doomemacs">DOOM</a> configuration framework, which pre-configures Magit and evil-mode and a bunch of amazing tools.
</p>
<p>
If you're not into editors older than you are, try <a href="https://zed.dev">Zed</a>, a modern editor that's fast and extensible. As a JOL-approved application you can find the demo version on the installation medium you were sent.
</p>
<h2>Font</h2>
<p>
Displayed in the beautiful <a href="https://berkeleygraphics.com/typefaces/berkeley-mono/">Berkeley Mono</a> typeface by Berkeley Graphics. Unless you're reading in an RSS reader, a browser's reader mode, or you've defined custom fonts (does anyone still do that? Do browsers even still let you?)
</p>

View file

@ -8,16 +8,6 @@
<p>I write here about those things, about general tech dorkery, and about my experience with being <strong>super</strong> trans and learning who I am.</p>
</div>
<div>
<h2>Recent Posts</h2>
<ul class="recent-posts">
<%= for post <- @posts do %>
<li>
<date><%= JOL.Blog.format_date(post.date) %></date>
<.link href={~p"/blog/#{post.slug}"}><%= post.title %> </.link>
</li>
<% end %>
</ul>
</div>
</div>

View file

@ -1,24 +1,3 @@
<h1 class="post-title">Current Status</h1>
<p>Last update: 22 Aug 2024 • from the Canady House in Uptown Westerville</p>
<h2>Reading</h2>
<p><a href="http://www.penguinrandomhouse.com/books/554241/the-bright-sword-by-lev-grossman/?cktype=prod&ref=PRH115DBB8203CD&linkid=PRH115DBB8203CD&cdi=4DF51DB6C8882719E0534FD66B0A1B04&template_id=28415&aid=randohouseinc9932-20">THE BRIGHT SWORD</a> by Lev Grossman.</p>
<p>I've read everything he's written since THE MAGICIANS, which is easily in my Top 3 Books, and his take on the Arthurian legends is so far hitting all the right buttons for me. (<em>Minor</em> spoiler, but any Aruthurian take with a trans Dinadan is automatically winning.)</p>
<h2>Tech</h2>
<p>Mostly just <a href="https://forge.sigill.zone/phoenix/jol/"> this site</a>, but I'm doing a lot of homelab stuff, mostly via <a href="https://portainer.io">Portainer</a>, which makes deploying containers really easy. And it's not Kubernetes!</p>
<h2>Gaming</h2>
<p>I <em>really</em> wanna run a <a href="https://poweredbylesbians.com/">Thirsty Sword Lesbian</a> campaign. And a monthly poker game. But organizing groups for both is, to put it mildly, fucking impossible.</p>
<p>Recently, I finished playing <a href="https://store.steampowered.com/app/2008920/Lorelei_and_the_Laser_Eyes/">LORELAI AND THE LASER EYES</a>. If you're into fiendish puzzles, mysterious narratives, incredible gameplay...just look play the damn game, it's amazing.</p>
<h2>Miscellanea</h2>
<ul>
<li>A lot of energy is going into personal family issues at the moment, which is good and necessary but also tiring.</li>
<li>Invisalign, at least for me, is absolutely worth the money, it turns out.</li>
<li>Without further imrpovement, my lingual frenectomy was...not.</li>
<li>It's weird having actual hope about the future of the country. It's not a lot but it's <em>there</em> in a way it wasn't when Biden was failing to meaningfully challenge Trump. Harris/Walz is a breath of fresh air.</li>
</ul>
More to come.

View file

@ -1,18 +0,0 @@
defmodule JOLWeb.TagController do
use JOLWeb, :controller
def index(conn, _params) do
conn
|> render(:index,
page_title: "Jess Uses These Tags",
tags: JOL.Blog.unique_tag_list)
end
def tag(conn, %{"tag" => tag}) do
conn
|> render(:tag,
tag: tag,
page_title: "Posts Filed Under #{tag}",
posts: JOL.Blog.get_posts_by_tag!(tag))
end
end

View file

@ -1,5 +0,0 @@
defmodule JOLWeb.TagHTML do
use JOLWeb, :html
embed_templates "tag_html/*"
end

View file

@ -1,9 +0,0 @@
<h1 class="post-title">Filed Under "<%= @tag %>"</h1>
<%= for post <- @posts do %>
<div class="post-summary">
<p class="post-date"><date><%= post.date %></date></p>
<h3> <.link href={~p"/blog/#{post.slug}"}><%= post.title %> </.link> </h3>
<p><%= raw post.lede %></p>
</div>
<% end %>

View file

@ -22,13 +22,10 @@ defmodule JOLWeb.Router do
pipe_through :browser
get "/", PageController, :home
get "/tags", PageController, :tags
get "/archive", PageController, :archive
get "/about", PageController, :about
get "/now", PageController, :now
get "/colophon", PageController, :colophon
get "/tags", TagController, :index
get "/tags/:tag", TagController, :tag
get "/blog", BlogController, :index
get "/blog/:slug", BlogController, :show

View file

@ -1,41 +0,0 @@
defmodule Mix.Tasks.GenPost do
@moduledoc "gen_post: Generate a new blog post."
@shortdoc "Generates a new blog post. Takes the title, and generates the rest."
use Mix.Task
@impl Mix.Task
def run([title]) do
dir = Application.app_dir(:jol, "priv/posts/blog/")
slug = title
|> String.downcase()
|> String.replace(" ", "-")
|> String.replace(~r/[^a-zA-Z0-9 -]/, "")
pubdate = DateTime.now!("America/New_York")
filename = "#{slug}.md"
filepath = "#{dir}/#{filename}"
if File.exists?(filepath) do
IO.puts(:stderr, "Already exists: priv/posts/blog/#{filename}")
IO.puts(:stderr, "Stop reusing blog titles!")
else
content = """
+++
slug = "#{slug}"
title = "#{title}"
date = #{DateTime.to_iso8601(pubdate)}
draft = false
[taxonomies]
# An array of quoted strings
tags = []
+++
"""
File.write(filepath, content)
IO.puts "Created: #{dir}#{filename}"
end
end
end

View file

@ -60,8 +60,7 @@ defmodule JOL.MixProject do
{:bandit, "~> 1.2"},
{:nimble_publisher, "~> 1.1.0"},
{:toml, "~> 0.7"},
{:atomex, "~> 0.3.0"},
{:tz, "~> 0.27"}
{:atomex, "~> 0.3.0"}
]
end

View file

@ -2,7 +2,6 @@
"atomex": {:hex, :atomex, "0.3.0", "19b5d1a2aef8706dbd307385f7d5d9f6f273869226d317492c396c7bacf26402", [:mix], [{:xml_builder, "~> 2.0.0", [hex: :xml_builder, repo: "hexpm", optional: false]}], "hexpm", "025dbc3a3e99380894791a093019f535d0ef6cf1916f6ec1b778ac107fcfc3e4"},
"bandit": {:hex, :bandit, "1.5.2", "ed0a41c43a9e529c670d0fd48371db4027e7b80d43b1942893e17deb8bed0540", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "35ddbdce7e8a2a3c6b5093f7299d70832a43ed2f4a1852885a61d334cab1b4ad"},
"castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"},
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"},
@ -15,21 +14,16 @@
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized"]},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
"mint": {:hex, :mint, "1.6.0", "88a4f91cd690508a04ff1c3e28952f322528934be541844d54e0ceb765f01d5e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "3c5ae85d90a5aca0a49c0d8b67360bbe407f3b54f1030a111047ff988e8fefaa"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
"nimble_publisher": {:hex, :nimble_publisher, "1.1.0", "49dee0f30536140268996660a5927d0282946949c35c88ccc6da11a19231b4b6", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "80fb42d8d1e34f41ff29fc2a1ae6ab86ea7b764b3c2d38e5268a43cf33825782"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"phoenix": {:hex, :phoenix, "1.7.12", "1cc589e0eab99f593a8aa38ec45f15d25297dd6187ee801c8de8947090b5a9d3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "d646192fbade9f485b01bc9920c139bfdd19d0f8df3d73fd8eaf2dfbe0d2837c"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.1", "96798325fab2fed5a824ca204e877b81f9afd2e480f581e81f7b4b64a5a477f2", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.17", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "0ae544ff99f3c482b0807c5cec2c8289e810ecacabc04959d82c3337f4703391"},
"phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
@ -41,7 +35,6 @@
"plug": {:hex, :plug, "1.16.0", "1d07d50cb9bb05097fdf187b31cf087c7297aafc3fed8299aac79c128a707e47", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cbf53aa1f5c4d758a7559c0bd6d59e286c2be0c6a1fac8cc3eee2f638243b93e"},
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
"postgrex": {:hex, :postgrex, "0.18.0", "f34664101eaca11ff24481ed4c378492fed2ff416cd9b06c399e90f321867d7e", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a042989ba1bc1cca7383ebb9e461398e3f89f868c92ce6671feb7ef132a252d1"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"swoosh": {:hex, :swoosh, "1.16.7", "9dd0c172b4519a023f58e94d3ea79480b469dd4c0cd5369fabfbfd2e39bf5545", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.1.0", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.4 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "21073982816cff3410e90c0d80ebfd5a0bf4839c7b39db20bc69a6df123bbf35"},
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
@ -49,9 +42,6 @@
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
"thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"},
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
"tz": {:hex, :tz, "0.27.1", "d8091d0c2d4f590e010c94830c3d842f548b4872a5b92028d74f0d0a3887aebe", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:mint, "~> 1.6", [hex: :mint, repo: "hexpm", optional: true]}], "hexpm", "215c9120dab5b7f7db4c93e91085c290b2efe478e147d84285a6583fd220727f"},
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
"xml_builder": {:hex, :xml_builder, "2.0.0", "371ed27bb63bf0598dbaf3f0c466e5dc7d16cb4ecb68f06a67f953654062e21b", [:mix], [], "hexpm", "baeb5c8d42204bac2b856ffd50e8cda42d63b622984538d18d92733e4e790fbd"},

View file

@ -1,24 +0,0 @@
+++
slug = "ruining-your-keyspace"
title = "Ruining Your Keyspace For Fun And Profit"
date = 2024-09-03T12:51:23.952866-04:00
draft = false
[taxonomies]
# An array of quoted strings
tags = ["tales", "cmm", "software"]
+++
![Apparently the Hulu activation codes can/could accidentally include hilarious stuff like 6 F A G S E X!](/images/hulu_badwords.jpg)
Oh, the memories.
One of the early design decisions at CoverMyMeds was to generate alphanumeric keys for each Prior Auth, to ease communication about them. We figured trying to get pharmacists to read UUIDs to folks over the phone was a losing proposition. Because it was early, we just slapped together a quick "generate key, check for existence, loop back and generate again if used" routine and shipped it.
As seems obvious in retrospect, we eventaully also generated a key that included the f-slur. Luckily, it was sent to an early partner who found this hilarious instead of wildly offensive. Having dodged a company-ending bullets -- not the first, for damn sure not the last -- we brainstormed a list of offensive words that could be generated, and denylisted them.
I mean, that's usually the end of the story, but this one has a fun addendum. Our "PA Key" keyspace, which was previously limited to "all the possible combinations of letters/numbers in our strict format," got even smaller after we implemented the denylist. That, plus some new partnerships that turned into gangbusters growth, meant that we had nearly no time between the "hey we're almost out of keys to use for PAs" alarm, and actually being completely out of keys.
Remember, our key generation routine now looked like "generate key, discard and retry if on denylist, discard and retry if already used." This happened inline during the POST request to create a new Prior Auth, which meant **all of our apache threads across all our production servers** were spinning, constantly regenerating keys. We'd DOSed ourselves. And it took us *a good while* to figure out the cause.
Lessons learned: maybe don't block the inital database CREATE waiting for keyspace to free up. Or maybe it was to just not have a feasibly bounded keyspace in the first place? I dunno, we just changed our key format to give us more keyspace and set up more alarms.

View file

@ -1,34 +0,0 @@
+++
slug = "thoughts-on-zed"
title = "Zed: Early Thoughts"
date = 2024-08-24T15:37:07.509694-04:00
draft = false
[taxonomies]
# An array of quoted strings
tags = ["software", "review"]
+++
![](/images/zed-screenshot.png)
I've been using [Zed](https://zed.dev) a bit, and as a software developer on the internet, I have *thoughts.*
I'm using it to write Elixir/Phoenix, HTML/CSS, and some Markdown, and it's trying to take the place of the venerable Emacs (running [DOOM](https://github.com/doomemacs/doomemacs)).
In no particular order:
* A truly open-source editor! Written in Rust! Finally, a modern editor that isn't a Microsoft embrace/extend/extinguish vector!
* Goddammit is that a Github sign-in link? Shit.
* The built-in vim mode isn't bad, but it pales in comparison to `evil-mode`. Specifically I can't highlight a region and `:%s/search/replace/g` inside it.
* I think having `:` open the command palette is a bad idea. The way one uses the command palette vs vim-style commands has less overlap than you'd think.
* It's pretty! Look I'm not immune to eye-candy, and Emacs has always ranked low in that area.
* I'm not getting anything from elixir-ls. Even *Emacs* automatically installs and sets that up so...y'know, damn. Two demerits, Mr. Zed.
* Same with speling check in things like Markdown files.
* Like most things, it ignores the "Emacs-keys" GTK setting &emdash; not being a GTK app I'm not shocked, but things like Firefox respect it, so it *can* be done. Ctrl-A not going to beginning of line, for instance.
* Not sure I love this though:
![the Zed Roadmap for 2024 includes "embrace AI" as one of the three items on the list.](/images/zed-roadmap-2024.png)
I'm running solo at the moment so I haven't tried any of the "multiplayer" remote-pairing stuff. I *believe* it's behind a Github-login though, and I wish that weren't the case.
Overall: three stars, worthy of your time and attention, also please stop using Microsoft products.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 KiB