summaryrefslogtreecommitdiff
path: root/http/src
diff options
context:
space:
mode:
Diffstat (limited to 'http/src')
-rw-r--r--http/src/blog.upphtml76
-rw-r--r--http/src/blog/rss.uppxml50
-rw-r--r--http/src/blog/subscribe.trivial.upphtml4
-rw-r--r--http/src/contact.upphtml96
-rw-r--r--http/src/css/base.uppcss515
-rw-r--r--http/src/css/feed.uppcss45
-rw-r--r--http/src/css/hcard.uppcss57
-rw-r--r--http/src/css/otp.uppcss29
-rw-r--r--http/src/css/post.uppcss8
-rw-r--r--http/src/css/reset.uppcss93
-rw-r--r--http/src/error.upphtml14
-rw-r--r--http/src/index.upphtml47
-rw-r--r--http/src/links/rss.trivial.upphtml4
-rw-r--r--http/src/microlog.upphtml84
-rw-r--r--http/src/microlog/rss.uppxml50
-rw-r--r--http/src/sitemap.uppxml21
-rw-r--r--http/src/subscribe.upphtml91
17 files changed, 0 insertions, 1284 deletions
diff --git a/http/src/blog.upphtml b/http/src/blog.upphtml
deleted file mode 100644
index 8c0e429..0000000
--- a/http/src/blog.upphtml
+++ /dev/null
@@ -1,76 +0,0 @@
-#!
-PAGE="$1"
-SITE_URL="$2"
-export TITLE="Joe Carstairs"
-export DESCRIPTION="Joe Carstairs' personal website"
-
-POSTS="$(ls --reverse "${SRC}/blog/" | grep "^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\.blog.upphtml$")"
-set --
-for post in $POSTS
-do
- this_year="$( echo "$post" | cut -c1-4 )"
- has_this_year=0
- for year in $@
- do
- if [ "$this_year" = "$year" ]
- then
- has_this_year=1
- break
- fi
- done
- if [ $has_this_year -eq 0 ]
- then
- set -- $@ "$this_year"
- fi
-done
-YEARS="$@"
-
-pp "${SHARE}"/components/meta.upphtml
-#!
-
-<section class='h-feed'>
-
-<h1>My blog</h1>
-
-<aside>
-<p>This blog is written by <a class='p-author h-card' href='/'>Joe Carstairs</a>.</p>
-<p hidden><a class='u-url' href='${SITE_URL}/blog'>Permalink</a></p>
-</aside>
-
-<section>
-<p><a href='/subscribe'>How to subscribe to my logs</a></p>
-</section>
-
-#!
-for year in $YEARS; do
-#!
-<h2>${year}</h2>
-
-<ul>
-
-#!
-for post in $POSTS; do if [ "$(echo "${post}" | cut -c1-4)" = "$year" ]; then
-title="$(grep "^export TITLE=" "${SRC}/blog/${post}" | cut -c15-)"
-title="$(echo ${title} | cut -c1-$(( ${#title} - 16 )) )"
-date_published="$(echo "${post}" | cut -c1-10)"
-href="${SITE_URL}/blog/$(echo "$post" | cut -c1-10).html"
-#!
-
-<li class='h-entry'>
-<h3><a class='u-url p-name' href='${href}'>${title}</a></h3>
-#!
-DATE="${date_published}" CLASS="dt-published" pp "${SHARE}/components/formatted_date.upphtml"
-#!
-</li>
-
-#!
-fi; done
-#!
-
-</ul>
-
-#!
-done
-#!
-
-</section>
diff --git a/http/src/blog/rss.uppxml b/http/src/blog/rss.uppxml
deleted file mode 100644
index 78800aa..0000000
--- a/http/src/blog/rss.uppxml
+++ /dev/null
@@ -1,50 +0,0 @@
-#!
-SITE_URL="$1"
-POSTS="$(ls --reverse "${SRC}/blog/" | grep "^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\(\.[0-9]\+\)\?\.blog.upphtml$")"
-NOW_RFC_822="$(TZ=UT date +"%a, %d %b %Y %H:%M:%S UT")"
-#!
-
-<rss version='2.0'>
-
-<channel>
-<title>Joe Carstairs’ blog</title>
-<description>Short posts on random topics I find interesting</description>
-<link>${SITE_URL}/blog</link>
-<image>${SITE_URL}/images/headshot.webp</image>
-<language>en-GB</language>
-<pubDate>${NOW_RFC_822}</pubDate>
-
-#!
-for post in $POSTS; do
-POST_ID="$(echo ${post} | cut -c1-$(( ${#post} - 13 )) )"
-. "${SRC}/blog/${post}.args"
-DATE_PUBLISHED_RFC_822="$(TZ=UT date --date="$( echo "${POST_ID}" | cut -c1-10)" +"%a, %d %b %Y %H:%M:%S UT")"
-#!
-<item>
-
-<title>${POST_TITLE}</title>
-<link>${SITE_URL}/blog/${POST_ID}</link>
-<guid isPermaLink='true'>${SITE_URL}/blog/${POST_ID}</guid>
-<pubDate>${DATE_PUBLISHED_RFC_822}</pubDate>
-<description>
-#!
-NO_META=1 pp "${SRC}/blog/$post" "${SITE_URL}" \
- | sed "s/&/\\&amp;/g" \
- | sed "s/</\\&lt;/g" \
- | sed "s/>/\\&gt;/g" \
- | sed "s/\"/\\&quot;/g" \
- | sed "s/'/\\&#x27;/g" \
- | sed "s/\`/\\&#x60;/g" \
- | sed "s/\\\$/\\\\\$/g"
-#!
-</description>
-<author>Joe Carstairs</author>
-
-</item>
-#!
-done
-#!
-
-</channel>
-
-</rss>
diff --git a/http/src/blog/subscribe.trivial.upphtml b/http/src/blog/subscribe.trivial.upphtml
deleted file mode 100644
index e842234..0000000
--- a/http/src/blog/subscribe.trivial.upphtml
+++ /dev/null
@@ -1,4 +0,0 @@
-#!
-SITE_URL="${1}"
-#!
-<meta http-equiv=refresh content=0;url=${SITE_URL}/subscribe />
diff --git a/http/src/contact.upphtml b/http/src/contact.upphtml
deleted file mode 100644
index 1f425a6..0000000
--- a/http/src/contact.upphtml
+++ /dev/null
@@ -1,96 +0,0 @@
-#!
-export TITLE="Contact"
-export DESCRIPTION="Contact Joe Carstairs"
-pp "${SHARE}"/components/meta.upphtml
-#!
-
-#!
-pp "${SHARE}"/components/otp-dialog.upphtml
-#!
-
-<form class=contact-form>
- <h1>Contact me</h1>
- <p hidden class=error></p>
- <label for=name>Name</label>
- <input id=name name=name type=text required>
- <label for=email>Email</label>
- <input id=email name=email type=email required>
- <label for=message>Message</label>
- <textarea id=message name=message required></textarea>
- <input type=submit value=Send>
-</form>
-
-<section class=success hidden=true>
- <h1>You sent me a message!</h1>
- <p>Thanks for that. I may be in touch.</p>
- <p>In case you forgot, your message was this:</p>
- <hr />
- <dl>
- <dt>Name</dt> <dd class=sentname>???</dd>
- <dt>Email</dt> <dd class=sentemail>???</dd>
- <dt>Message</dt> <dd class=sentmessage>???</dd>
- </dl>
-</section>
-
-<script type=module>
- import { resendOtp } from '/scripts/contact/resend-otp.js';
- import { submitContactForm } from '/scripts/contact/submit-contact-form.js';
- import { submitOtpForm } from '/scripts/contact/submit-otp-form.js';
-
- function locateOrPanic(selector, desc, root) {
- const elem = (root ?? document).querySelector(selector);
- if (!elem) {
- alert('Technical error: could not locate ' + desc + '. Please let Joe know if you have another means of contacting him.');
- throw new Error('Could not locate ' + desc);
- }
- return elem;
- }
-
- const contactForm = locateOrPanic('form.contact-form', 'contact form');
- const otpDialog = locateOrPanic('dialog.otp-dialog', 'OTP dialog');
- const otpForm = locateOrPanic('form.otp-form', 'OTP form');
- const successSection = document.querySelector('section.success');
- let resendButtonInterval = undefined;
-
- const selectors = {
- contactForm: {
- emailElem: () => locateOrPanic('input[name=email]', 'email input', contactForm),
- errorElem: () => contactForm.querySelector('.error'),
- nameElem: () => locateOrPanic('input[name=name]', 'name input', contactForm),
- messageElem: () => locateOrPanic('textarea[name=message]', 'message textarea', contactForm),
- self: () => contactForm,
- submitButton: () => contactForm.querySelector('input[type=submit]'),
- },
- otpDialog: {
- allOtpInputs: () => otpForm.querySelectorAll('input:not([type=submit])'),
- errorElem: () => otpDialog.querySelector('.error'),
- firstOtpInput: () => otpForm.querySelector('input:not([type=submit]):first-child'),
- otpForm: () => otpForm,
- otpRecipient: () => otpDialog.querySelector('.otp-recipient'),
- otpValidUntil: () => otpDialog.querySelector('.otp-valid-until'),
- resendButton: () => otpDialog.querySelector('button.resend-button'),
- self: () => otpDialog,
- submitButton: () => otpForm.querySelector('input[type=submit]'),
- },
- successSection: {
- email: () => successSection?.querySelector('.sentemail') ?? null,
- name: () => successSection?.querySelector('.sentname') ?? null,
- message: () => successSection?.querySelector('.sentmessage') ?? null,
- self: () => successSection,
- }
- };
-
- contactForm.addEventListener('submit', async (event) => {
- event.preventDefault();
- ({ resendButtonInterval } = await submitContactForm(selectors, resendButtonInterval));
- });
-
- selectors.otpDialog.resendButton()?.addEventListener('click', async () => {
- ({ resendButtonInterval } = await resendOtp(selectors, resendButtonInterval));
- });
-
- otpForm.addEventListener('submit', async (event) => {
- event.preventDefault();
- await submitOtpForm(selectors);
- });
-</script>
diff --git a/http/src/css/base.uppcss b/http/src/css/base.uppcss
deleted file mode 100644
index b0e8565..0000000
--- a/http/src/css/base.uppcss
+++ /dev/null
@@ -1,515 +0,0 @@
-/** Variables */
-
-:root {
- --colour-primary-10: #060300;
- --colour-primary-15: #150800;
- --colour-primary-20: #1f1400;
- --colour-primary-30: #3c2b00;
- --colour-primary-40: #5c4300;
- --colour-primary-50: #7f5d00;
- --colour-primary-60: #a37800;
- --colour-primary-70: #c89500;
- --colour-primary-80: #efb300;
- --colour-primary-90: #ffd98c;
- --colour-primary-95: #ffecc8;
-
- --colour-hyperlink-10: #000409;
- --colour-hyperlink-20: #001829;
- --colour-hyperlink-30: #00314d;
- --colour-hyperlink-40: #004d75;
- --colour-hyperlink-50: #006a9f;
- --colour-hyperlink-60: #1388c9;
- --colour-hyperlink-70: #41a8ea;
- --colour-hyperlink-80: #78c7ff;
- --colour-hyperlink-90: #bfe3ff;
- --colour-hyperlink-95: #e0f1ff;
-
- --colour-grey-10: oklch(0.1 0.01 84);
- --colour-grey-20: oklch(0.2 0.01 84);
- --colour-grey-30: oklch(0.3 0.01 84);
- --colour-grey-40: oklch(0.4 0.01 84);
- --colour-grey-50: oklch(0.5 0.01 84);
- --colour-grey-60: oklch(0.6 0.01 84);
- --colour-grey-70: oklch(0.7 0.01 84);
- --colour-grey-80: oklch(0.8 0.01 84);
- --colour-grey-90: oklch(0.9 0.01 84);
- --colour-grey-95: oklch(0.95 0.01 84);
-
- --colour-error-10: oklch(0.1 0.2 26);
- --colour-error-20: oklch(0.2 0.2 26);
- --colour-error-30: oklch(0.3 0.2 26);
- --colour-error-40: oklch(0.4 0.2 26);
- --colour-error-50: oklch(0.5 0.2 26);
- --colour-error-60: oklch(0.6 0.2 26);
- --colour-error-70: oklch(0.7 0.2 26);
- --colour-error-80: oklch(0.8 0.2 26);
- --colour-error-90: oklch(0.9 0.2 26);
- --colour-error-95: oklch(0.95 0.2 26);
-
- --colour-warn-10: oklch(0.1 0.2 46);
- --colour-warn-20: oklch(0.2 0.2 46);
- --colour-warn-30: oklch(0.3 0.2 46);
- --colour-warn-40: oklch(0.4 0.2 46);
- --colour-warn-50: oklch(0.5 0.2 46);
- --colour-warn-60: oklch(0.6 0.2 46);
- --colour-warn-70: oklch(0.7 0.2 46);
- --colour-warn-80: oklch(0.8 0.2 46);
- --colour-warn-90: oklch(0.9 0.2 46);
- --colour-warn-95: oklch(0.95 0.2 46);
-
- --colour-primary-fg: var(--colour-primary-90);
- --colour-primary-fg-accent: var(--colour-primary-80);
- --colour-primary-bg: var(--colour-primary-10);
- --colour-primary-bg-accent: var(--colour-primary-20);
- --colour-code-fg: var(--colour-primary-90);
- --colour-code-bg: var(--colour-primary-15);
- --colour-hyperlink: var(--colour-hyperlink-80);
- --colour-grey-fg: var(--colour-grey-70);
- --colour-grey-bg: var(--colour-grey-30);
- --colour-error-fg: var(--colour-error-90);
- --colour-error-bg: var(--colour-error-40);
- --colour-warn-fg: var(--colour-warn-20);
- --colour-warn-bg: var(--colour-warn-80);
-
- --font-size-sm: 1rem;
- --font-size-base: 1.125rem;
- --font-size-md: 1.5rem;
- --font-size-lg: 2rem;
- --font-size-xl: 3rem;
-
- --spacing-block-xs: 0.5rem;
- --spacing-block-sm: 1.75rem;
- --spacing-block-md: 2.5rem;
- --spacing-block-lg: 3.5rem;
- --spacing-block-xl: 5rem;
- --spacing-inline-xs: 0.25rem;
- --spacing-inline-sm: 0.5rem;
- --spacing-inline-md: 1.5rem;
- --spacing-inline-lg: 3rem;
- --spacing-inline-xl: 6rem;
-}
-
-/** Light theme */
-@media (prefers-color-scheme: light) {
- :root {
- --colour-primary-fg: var(--colour-primary-20);
- --colour-primary-fg-accent: var(--colour-primary-40);
- --colour-primary-bg: var(--colour-primary-95);
- --colour-hyperlink: var(--colour-hyperlink-40);
- --colour-grey-fg: var(--colour-grey-40);
- --colour-grey-bg: var(--colour-grey-80);
- --colour-error-fg: var(--colour-error-20);
- --colour-error-bg: var(--colour-error-80);
- }
-}
-
-/** Base typography */
-
-body {
- font-size: var(--font-size-base);
- color: var(--colour-primary-fg);
- font-weight: light;
- background-color: var(--colour-primary-bg);
- line-height: 1.5;
-
- /* Geometric Humanist stack from https://modernfontstacks.com */
- font-family:
- Avenir, Montserrat, Corbel, 'URW Gothic', source-sans-pro, sans-serif;
-}
-
-small {
- font-size: var(--font-size-sm);
-}
-
-:is(p, h1, h2, h3, h4, h5, h6, hr, img, figure, ul, ol, blockquote) {
- margin-block-start: var(--spacing-block-sm);
-}
-
-hr {
- height: 2px;
-}
-
-/** Base layout */
-
-body {
- --body-margin-inline-start: var(--spacing-inline-lg);
- --body-margin-inline-end: var(--body-margin-inline-start);
- --body-margin-block-end: var(--spacing-block-xl);
- margin-inline: var(--body-margin-inline-start) var(--body-margin-inline-end);
- margin-block-end: var(--body-margin-block-end);
-}
-
-:is(h1, h2, h3, h4, h5, h6) {
- text-align: center;
-}
-
-img {
- margin-inline: auto;
- height: auto;
-}
-
-@media (min-width: 60rem) {
- body {
- display: grid;
- grid-template-columns:
- [grid-start media-start]
- var(--grid-margin-inline)
- [media-end content-start]
- minmax(var(--grid-max-content-width), auto)
- [content-end grid-end];
- grid-auto-rows: max-content;
- column-gap: var(--spacing-block-sm);
- max-width: var(--grid-total-width);
-
- --body-margin-inline-end: 6rem;
- --grid-margin-inline: 6rem;
- --grid-total-width: 48rem;
- --grid-max-content-width: calc(
- var(--grid-total-width) - var(--body-margin-inline-start) -
- var(--grid-margin-inline) - var(--spacing-block-sm) -
- var(--grid-margin-inline)
- );
- }
-
- :is(main, article, nav) {
- display: grid;
- grid-column: grid;
- grid-template-columns: subgrid;
-
- > :is(section, header, aside, form) {
- display: grid;
- grid-template-columns: subgrid;
- grid-column: grid;
-
- > :not(.not-grid-content) {
- grid-column: content;
- }
- }
- }
-
- :is(h1, h2, h3, h4, h5, h6) {
- text-align: start;
- }
-}
-
-@media (min-width: 80rem) {
- body {
- grid-template-columns:
- [grid-start media-start]
- var(--grid-margin-inline)
- [media-end content-start]
- minmax(auto, var(--grid-max-content-width))
- [content-end margin-start]
- auto
- [margin-end grid-end];
-
- --grid-total-width: 80rem;
- --grid-max-content-width: 40rem;
- }
-}
-
-/** Headings */
-
-h1 {
- font-size: var(--font-size-xl);
- font-weight: 900;
- margin-block-start: 0;
-}
-
-h2 {
- font-size: var(--font-size-lg);
- font-weight: 900;
- margin-block-start: var(--spacing-block-xl);
-}
-
-h3,
-h4,
-h5,
-h6 {
- font-size: var(--font-size-md);
- font-weight: 600;
- margin-block-start: var(--spacing-block-lg);
-}
-
-/** Hyperlinks */
-
-a:is(:link, :visited) {
- color: var(--colour-hyperlink);
- text-decoration: underline;
- display: inline;
-}
-
-a:hover {
- text-decoration: wavy;
-}
-
-/** Definition lists */
-dl {
- margin-block-start: var(--spacing-block-md);
-}
-
-dl dt {
- font-weight: bold;
-}
-
-dl dd + dt {
- margin-block-start: var(--spacing-block-md);
-}
-
-/** figcaptions */
-
-figcaption {
- font-size: var(--font-size-sm);
- font-style: italic;
- text-align: center;
-}
-
-/** Lists */
-
-:is(ol, ul) {
- margin-inline-start: var(--spacing-inline-lg);
-}
-
-/** Navigation bar */
-
-nav {
- margin-block: var(--spacing-block-sm);
-}
-
-nav ul {
- grid-column: media-start / content-end;
- display: flex;
- justify-content: center;
- gap: var(--spacing-inline-md);
- list-style: none;
- margin: 0;
-}
-
-@media (min-width: 36rem) {
- nav {
- display: grid;
- grid-template-columns: subgrid;
- }
-
- nav ul {
- justify-content: end;
- }
-}
-
-/** Emphasis */
-
-strong {
- font-weight: bold;
- font-style: italic;
-}
-
-/** Blog feed */
-
-/** Block quotes */
-blockquote {
- padding-inline-start: var(--spacing-inline-lg);
- border-inline-start: 2px solid var(--colour-primary-fg);
- font-style: italic;
-}
-
-blockquote :first-child {
- margin-block-start: 0;
-}
-
-blockquote footer {
- font-style: initial;
-}
-
-blockquote :is(b, strong) {
- font-style: italic;
- font-weight: bold;
-}
-
-blockquote :is(i, em) {
- font-style: normal;
-}
-
-/** Small caps */
-.small-caps {
- font-variant: small-caps;
-}
-
-/** Pre-formatted blocks */
-pre {
- border: 2px solid var(--colour-primary-fg);
- border-radius: 2px;
- background-color: var(--colour-code-bg) !important;
- margin-block-start: var(--spacing-block-sm);
- padding-inline: var(--spacing-inline-sm);
- padding-block: var(--spacing-block-xs);
-}
-
-/** Code blocks */
-code {
- border: 2px solid var(--colour-primary-fg);
- border-radius: 2px;
- padding-inline: var(--spacing-inline-xs);
- color: var(--colour-code-fg);
- background-color: var(--colour-code-bg);
- font-size: var(--font-size-sm);
-}
-pre code {
- border: none;
- border-radius: none;
- padding: none;
-}
-
-/* verse */
-.verse {
- span {
- display: block;
- }
-}
-.verse--hanging-indents {
- span + span:not(.not-hanging) {
- margin-inline-start: var(--spacing-inline-md);
- }
-}
-
-/* block-comment */
-block-comment {
- display: grid;
- grid-template-columns: subgrid;
- grid-column: grid;
-
- > * {
- grid-column: content;
- }
-
- > blockquote:last-of-type {
- padding-block: var(--spacing-block-sm);
- padding-inline: var(--spacing-inline-md);
- overflow-y: scroll;
- border: 2px solid var(--colour-primary-fg);
- --colour-scroll-shadow: color-mix(
- in srgb,
- var(--colour-primary-fg),
- transparent 20%
- );
-
- background:
- linear-gradient(var(--colour-primary-bg) 30%, transparent) center top,
- linear-gradient(transparent, var(--colour-primary-bg) 70%) center bottom,
- radial-gradient(
- farthest-side at 50% 0,
- var(--colour-scroll-shadow),
- transparent
- )
- center top,
- radial-gradient(
- farthest-side at 50% 100%,
- var(--colour-scroll-shadow),
- transparent
- )
- center bottom;
- background-repeat: no-repeat;
- background-size:
- 100% 2rem,
- 100% 2rem,
- 100% 1rem,
- 100% 1rem;
- background-attachment: local, local, scroll, scroll;
-
- > :first-child {
- margin-block-start: 0;
- }
- }
-}
-
-@media (min-width: 80rem) {
- block-comment > blockquote:last-of-type {
- grid-column: margin;
- max-height: 67vh;
- }
-}
-
-/* forms */
-form {
- margin-inline: auto;
- max-width: max-content;
-
- :is(button, fieldset, input, label, object, output, select, textarea, img) {
- display: block;
- }
-
- label {
- margin-block-end: var(--spacing-block-xs);
- }
-
- * + :is(label, input[type='submit'], button) {
- margin-block-start: var(--spacing-block-md);
- }
-
- :is(input[type='submit'], input[type='button'], button) {
- padding-inline: var(--spacing-inline-sm);
- max-width: max-content;
- &:not(dialog *) {
- margin-inline-start: auto;
- }
- }
-
- :is(input[type='email'], input[type='text'], select) {
- max-width: 100%;
- width: 16rem;
- }
-
- textarea {
- max-width: 100%;
- width: 40rem;
- }
-}
-
-/* dialogs */
-
-dialog {
- background: var(--colour-primary-bg-accent);
- border: 2px solid var(--colour-primary-fg-accent);
- bottom: auto;
- color: var(--colour-primary-fg);
- left: calc(0.5 * (100vw - min(90vw, 36rem)));
- margin: 0;
- padding-block: var(--spacing-block-sm);
- padding-inline: var(--spacing-inline-sm);
- text-align: center;
- top: auto;
- width: min(90vw, 36rem);
-}
-
-@media (min-width: 80rem) {
- dialog {
- left: calc(
- var(--body-margin-inline-start) + var(--grid-margin-inline) + 2 *
- var(--spacing-inline-md)
- );
- }
-}
-
-/* utilities */
-:is(
- .para-spacing-tight:is(p, h1, h2, h3, h4, h5, h6, hr, img, figure, ul, ol),
- .para-spacing-tight :is(p, h1, h2, h3, h4, h5, h6, hr, img, figure, ul, ol)
-) {
- margin-block-start: var(--spacing-block-xs);
-}
-
-.error {
- background: var(--colour-error-bg);
- border: 2px solid var(--colour-error-fg);
- color: var(--colour-error-fg);
- padding-block: var(--spacing--block-sm);
- padding-inline: var(--spacing-inline-sm);
-}
-
-.warn {
- background: var(--colour-warn-bg);
- border: 2px solid var(--colour-warn-fg);
- color: var(--colour-warn-fg);
- padding-block: var(--spacing--block-sm);
- padding-inline: var(--spacing-inline-sm);
- --colour-hyperlink: var(--colour-hyperlink-40);
-}
diff --git a/http/src/css/feed.uppcss b/http/src/css/feed.uppcss
deleted file mode 100644
index 60fcd6d..0000000
--- a/http/src/css/feed.uppcss
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Assumes there is at most one level of subheading for sub-dividing entries */
-.h-feed :is(h2, h3, h4, h5, h6) {
- margin-block-start: var(--spacing-block-md);
-}
-
-.h-feed ul:has(> .h-entry) {
- list-style-type: none;
- margin-inline: 0;
-
- ul {
- list-style-type: disc;
- }
-}
-
-.h-feed .h-entry {
- display: flex;
- flex-direction: column;
-}
-
-.h-feed .h-entry + .h-entry {
- margin-block-start: var(--spacing-block-md);
-}
-
-.h-feed .h-entry > * {
- order: 1;
- margin: 0;
-}
-
-.h-feed .h-entry .dt-published {
- order: 0;
- font-size: var(--font-size-sm);
-}
-
-.h-feed .h-entry .p-name {
- font-size: var(--font-size-md);
- font-weight: 400;
-}
-
-.h-feed .full-feed-link {
- text-align: end;
-}
-
-.h-feed :is(a.full-feed-link, .full-feed-link a)::after {
- content: ' >';
-}
diff --git a/http/src/css/hcard.uppcss b/http/src/css/hcard.uppcss
deleted file mode 100644
index 7908bc8..0000000
--- a/http/src/css/hcard.uppcss
+++ /dev/null
@@ -1,57 +0,0 @@
-.h-card div:has(img) {
- width: 6rem;
- height: 6rem;
- margin-inline: auto;
-}
-
-.h-card img {
- width: 6rem;
- height: 6rem;
- border-radius: 1rem;
- filter: contrast(1.25);
-}
-
-.h-card div:has(img)::after {
- /* Colour overlay */
- background-color: var(--colour-primary-80);
- opacity: 0.3;
-
- /* Same size and shape as the img */
- border-radius: 1rem;
- width: 6rem;
- height: 6rem;
-
- /* Positioned on top of the img */
- display: block;
- position: relative;
- top: -6rem;
-
- /* A content value is needed to get the ::after to render */
- content: '';
-}
-
-@media (min-width: 36rem) {
- .h-card {
- grid-column: media-start / content-end;
- display: grid;
- grid-template-columns: subgrid; /** Subgrid of main column layout */
- grid-template-rows: min-content 1fr;
- grid-template-areas:
- 'empty heading'
- 'photo text';
- column-gap: var(--spacing-block-sm);
- }
-
- .h-card div:has(img) {
- grid-area: photo;
- margin-block-start: var(--spacing-block-sm);
- }
-
- .h-card header {
- grid-area: heading;
- }
-
- .h-card__text {
- grid-area: text;
- }
-}
diff --git a/http/src/css/otp.uppcss b/http/src/css/otp.uppcss
deleted file mode 100644
index 47a74d3..0000000
--- a/http/src/css/otp.uppcss
+++ /dev/null
@@ -1,29 +0,0 @@
-.otp-inputs {
- display: flex;
- flex-direction: row;
- gap: var(--spacing-inline-sm);
- justify-content: center;
-
- input {
- border: none;
- border-block-end: 2px solid var(--colour-grey-fg);
- font-size: var(--font-size-lg);
- text-align: center;
- width: var(--font-size-lg);
- }
-}
-
-.otp-form {
- align-items: center;
- display: flex;
- flex-direction: column;
- gap: var(--spacing-block-sm);
-
- > * {
- margin: 0;
- }
-
- input[type='submit'] {
- max-width: max-content;
- }
-}
diff --git a/http/src/css/post.uppcss b/http/src/css/post.uppcss
deleted file mode 100644
index 436c13e..0000000
--- a/http/src/css/post.uppcss
+++ /dev/null
@@ -1,8 +0,0 @@
-.p-summary {
- font-style: italic;
- font-size: var(--font-size-sm);
-}
-
-h1 {
- margin-block-start: var(--spacing-block-md);
-}
diff --git a/http/src/css/reset.uppcss b/http/src/css/reset.uppcss
deleted file mode 100644
index 03df124..0000000
--- a/http/src/css/reset.uppcss
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Based on Andy Bell’s More Modern CSS Reset: https://piccalil.li/blog/a-more-modern-css-reset/ */
-
-/* Box sizing rules */
-*,
-*::before,
-*::after {
- box-sizing: border-box;
-}
-
-/* Prevent font size inflation */
-html {
- -moz-text-size-adjust: none;
- -webkit-text-size-adjust: none;
- text-size-adjust: none;
-}
-
-/* Remove default margin in favour of better control in authored CSS */
-body,
-h1,
-h2,
-h3,
-h4,
-p,
-figure,
-blockquote,
-dl,
-dd {
- margin-block: 0;
-}
-
-/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
-ul[role='list'],
-ol[role='list'] {
- list-style: none;
-}
-
-/* Set core body defaults */
-body {
- min-height: 100vh;
-}
-
-/* Set shorter line heights on headings and interactive elements */
-h1,
-h2,
-h3,
-h4,
-button,
-input,
-label {
- line-height: 1.1;
-}
-
-/* Balance text wrapping on headings */
-h1,
-h2,
-h3,
-h4 {
- text-wrap: balance;
-}
-
-/* Make images easier to work with */
-img,
-picture {
- max-width: 100%;
- display: block;
-}
-
-/* Inherit fonts for inputs and buttons */
-input,
-button,
-textarea,
-select {
- font: inherit;
-}
-
-/* Make sure textareas without a rows attribute are not tiny */
-textarea:not([rows]) {
- min-height: 10em;
-}
-
-/* Anything that has been anchored to should have extra scroll margin */
-:target {
- scroll-margin-block: 5ex;
-}
-
-* {
- margin: 0;
- padding: 0;
-}
-
-[hidden] {
- display: none;
-}
diff --git a/http/src/error.upphtml b/http/src/error.upphtml
deleted file mode 100644
index 057006f..0000000
--- a/http/src/error.upphtml
+++ /dev/null
@@ -1,14 +0,0 @@
-#!
-export TITLE="Got lost?"
-export DESCRIPTION="Error page for Joe Carstairs' personal website"
-pp "${SHARE}"/components/meta.upphtml
-#!
-
-<section>
- <h1>Got lost?</h1>
-
- <p>
- If you’re on this page, something’s probably gone wrong. Try going to
- my <a href='/'>homepage</a> instead.
- </p>
-</section>
diff --git a/http/src/index.upphtml b/http/src/index.upphtml
deleted file mode 100644
index fec3774..0000000
--- a/http/src/index.upphtml
+++ /dev/null
@@ -1,47 +0,0 @@
-#!
-export TITLE="Joe Carstairs"
-export DESCRIPTION="Joe Carstairs' personal website"
-pp "${SHARE}"/components/meta.upphtml
-#!
-
-<section class="h-card">
- <div>
- <img class="u-photo" src="/images/headshot.webp" height="96" width="96" />
- </div>
-
- <header>
- <h1>Joe Carstairs</h1>
- <div hidden>
- <a class="p-name u-url u-uid" href="https://joeac.net" rel="me">
- Permalink
- </a>
- </div>
- </header>
-
- <div class="h-card__text">
- <p>
- Hi! 👋 My name is <span class="p-given-name">Joe</span>
- <span class="p-family-name">Carstairs</span>. I’m a
- <span class="p-job-title">software developer</span> at
- <a class="p-org" href="https://www.scottlogic.com">Scott Logic</a>,
- a Divinity student at the University of Edinburgh,
- a lapsed fiddle player and a very occasional poet.
- </p>
-
- <p>
- HMU with your thoughts on Elizabethan poetry, connecting to the
- Internet, and the Apocalypse of Saint John.
- </p>
-
- <p>
- <small>
- Or get me on
- <a href="https://www.facebook.com/joe.carstairs.5" rel="me">Facebook</a>,
- <a href="https://mastodon.social/@joe_carstairs" rel="me">Mastodon</a>,
- <a href="https://www.linkedin.com/in/joe-carstairs-0aa936277" rel="me">LinkedIn</a>,
- <a href="https://bsky.app/profile/joeacarstairs.bsky.social" rel="me">BlueSky</a>,
- or <a href="https://github.com/joeacarstairs" rel="me">GitHub</a>.
- </small>
- </p>
- </div>
-</section>
diff --git a/http/src/links/rss.trivial.upphtml b/http/src/links/rss.trivial.upphtml
deleted file mode 100644
index 52becef..0000000
--- a/http/src/links/rss.trivial.upphtml
+++ /dev/null
@@ -1,4 +0,0 @@
-#!
-SITE_URL="${1}"
-#!
-<meta http-equiv=refresh content=0;url=${SITE_URL}/microlog/rss.xml />
diff --git a/http/src/microlog.upphtml b/http/src/microlog.upphtml
deleted file mode 100644
index aa3cfea..0000000
--- a/http/src/microlog.upphtml
+++ /dev/null
@@ -1,84 +0,0 @@
-#!
-PAGE="$1"
-SITE_URL="$2"
-export TITLE="Joe Carstairs"
-export DESCRIPTION="Joe Carstairs' personal website"
-
-POSTS="$(ls --reverse "${SRC}/microlog/" | grep "^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\(\.[0-9]\+\)\?\.microlog.upphtml$")"
-set --
-for post in $POSTS
-do
- this_year="$( echo "$post" | cut -c1-4 )"
- has_this_year=0
- for year in $@
- do
- if [ "$this_year" = "$year" ]
- then
- has_this_year=1
- break
- fi
- done
- if [ $has_this_year -eq 0 ]
- then
- set -- $@ "$this_year"
- fi
-done
-YEARS="$@"
-
-pp "${SHARE}"/components/meta.upphtml
-#!
-
-<main>
-
-<section class='h-feed'>
-
-<h1>My microlog</h1>
-
-<aside>
-<p>This microlog is written by <a class='p-author h-card' href='/'>Joe Carstairs</a>.</p>
-<p hidden><a class='u-url' href='${SITE_URL}/microlog'>Permalink</a></p>
-</aside>
-
-<section>
-<p><a href='/subscribe'>How to subscribe to my logs</a></p>
-</section>
-
-#!
-for year in $YEARS; do
-#!
-<h2>${year}</h2>
-
-<ul>
-
-#!
-for post in $POSTS; do if [ "$(echo "${post}" | cut -c1-4)" = "$year" ]; then
-title="$(grep "^export TITLE=" "${SRC}/microlog/${post}" | cut -c15-)"
-title="$(echo "${title}" | cut -c1-$(( ${#title} - 16)) )"
-date_published="$(echo "${post}" | cut -c1-10)"
-href="${SITE_URL}/microlog/$(echo ${post} | cut -c1-$(( ${#post} - 17 )) ).html"
-#!
-
-<li class='h-entry'>
-<h3><a class='u-url p-name' href='${href}'>${title}</a></h3>
-<section class='e-content'>
-#!
-pp "${SRC}/microlog/${post}" "${SITE_URL}"
-#!
-</section>
-#!
-DATE="${date_published}" CLASS="dt-published" ATTRIBUTES="hidden" \
- pp "${SHARE}/components/formatted_date.upphtml"
-#!
-</li>
-
-#!
-fi; done
-#!
-
-</ul>
-
-#!
-done
-#!
-
-</section>
diff --git a/http/src/microlog/rss.uppxml b/http/src/microlog/rss.uppxml
deleted file mode 100644
index 20a6ced..0000000
--- a/http/src/microlog/rss.uppxml
+++ /dev/null
@@ -1,50 +0,0 @@
-#!
-SITE_URL="$1"
-POSTS="$(ls --reverse "${SRC}/microlog/" | grep "^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\(\.[0-9]\+\)\?\.microlog.upphtml$")"
-NOW_RFC_822="$(TZ=UT date +"%a, %d %b %Y %H:%M:%S UT")"
-#!
-
-<rss version='2.0'>
-
-<channel>
-<title>Joe Carstairs’ microlog</title>
-<description>My private X feed I guess?</description>
-<link>${SITE_URL}/microlog</link>
-<image>${SITE_URL}/images/headshot.webp</image>
-<language>en-GB</language>
-<pubDate>${NOW_RFC_822}</pubDate>
-
-#!
-for post in $POSTS; do
-POST_ID="$(echo ${post} | cut -c1-$(( ${#post} - 17 )) )"
-. "${SRC}/microlog/${post}.args"
-DATE_PUBLISHED_RFC_822="$(TZ=UT date --date="$( echo "${POST_ID}" | cut -c1-10)" +"%a, %d %b %Y %H:%M:%S UT")"
-#!
-<item>
-
-<title>${POST_TITLE}</title>
-<link>${SITE_URL}/microlog/${POST_ID}</link>
-<guid isPermaLink='true'>${SITE_URL}/microlog/${POST_ID}</guid>
-<pubDate>${DATE_PUBLISHED_RFC_822}</pubDate>
-<description>
-#!
-NO_META=1 pp "${SRC}/microlog/$post" "${SITE_URL}" \
- | sed "s/&/\\&amp;/g" \
- | sed "s/</\\&lt;/g" \
- | sed "s/>/\\&gt;/g" \
- | sed "s/\"/\\&quot;/g" \
- | sed "s/'/\\&#x27;/g" \
- | sed "s/\`/\\&#x60;/g" \
- | sed "s/\\\$/\\\\\$/g"
-#!
-</description>
-<author>Joe Carstairs</author>
-
-</item>
-#!
-done
-#!
-
-</channel>
-
-</rss>
diff --git a/http/src/sitemap.uppxml b/http/src/sitemap.uppxml
deleted file mode 100644
index bfcf8d8..0000000
--- a/http/src/sitemap.uppxml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>
-#!
-for f in $(find "${OUT}" -name "*.html")
-do
-#!
-<url>
-#!
-loc=$1/$(basename "${f}")
-#!
-<loc>${loc}</loc>
-#!
-lastmod=$(lmt -f '%Y-%m-%dT%H:%M:%SZ' "${f}" | cut -d' ' -f1)
-#!
-<lastmod>${lastmod}</lastmod>
-<priority>1.0</priority>
-</url>
-#!
-done
-#!
-</urlset>
diff --git a/http/src/subscribe.upphtml b/http/src/subscribe.upphtml
deleted file mode 100644
index 606e5c5..0000000
--- a/http/src/subscribe.upphtml
+++ /dev/null
@@ -1,91 +0,0 @@
-#!
-PAGE="$1"
-SITE_URL="$2"
-export TITLE="How to subscribe to joeac's blog"
-export DESCRIPTION="How to subscribe to joeac's blog"
-#!
-
-<section>
-<h1>How to subscribe to my logs</h1>
-
-<p>
-The short version: use my <a href='/blog/rss.xml'>blog RSS feed</a> and
-<a href='/microlog/rss.xml'>microlog RSS feed</a>, or my
-<a href='gemini://joeac.net/logs/loglog.gmi'>gemlog</a>.
-</p>
-
-<p>
-If neither of those things means anything to you, no worries. You could just
-look at my website every once in a while, but that gets old. A better way is to
-use my RSS file. Here's how.
-</p>
-
-<p>
-An RSS file, if you don't know, is a file containing a list of posts in a format
-that's so stupid even computers can understand it. Mine is at
-<a href='https://joeac.net/rss.xml'>https://joeac.net/rss.xml</a>,
-and I've also got one for just my blog posts at
-<a href='https://joeac.net/blog/rss.xml'>https://joeac.net/blog/rss.xml</a>,
-and one just for microlog posts at
-<a href='https://joeac.net/microlog/rss.xml'>https://joeac.net/microlog/rss.xml</a>.
-Since computers can understand it, you can get software to read it automatically
-and tell you when I've made a new blog post. That's much less hassle than having
-to check manually yourself!
-</p>
-
-<p>
-I'm not the only person serving RSS files, of course. You might not have heard
-of them, but they're actually all over the Web. In the early days of the Web,
-everyone was using them, so they've ended up built in to a whole load of
-foundational Web technology, and hence ubiquitous, even if most Web users have
-forgotten they exist. Once you've subscribed to my logs, you can subscribe to
-basically any blog, podcast, or YouTube channel, and a lot of other Websites for
-news, organisations, whatever. Point a well-designed RSS aggregator or RSS
-reader at most Websites, and it'll automatically find an associated RSS feed.
-</p>
-
-<p>
-If you're not persuaded, try reading
-<a href='https://doctorow.medium.com/you-should-be-using-an-rss-reader-76aed31151f9'>
-Cory Doctorow explaining why RSS is ridiculously good
-</a>. He's terrifyingly persuasive. Also, read his novels!
-</p>
-
-<p>
-If you just want to give it a go quickly, probably the quickest way is to
-use someone else's RSS aggregator that they'll let you use as a service.
-<a href='https://feedly.com/news-reader'>Feedly</a> and
-<a href='https://www.inoreader.com'>Inoreader</a> have free tiers.
-</p>
-
-<p>
-If you want to have a little more control, you can self-host an RSS
-reader, like <a href='https://tt-rss.org'>Tiny Tiny RSS</a>,
-<a href='https://miniflux.app'>Miniflux</a>, or
-<a href='https://freshrss.org'>FreshRSS</a>. But why would you do that?
-Self-hosting is complicated! Why not just use a normal, local app? Here are
-some options for that you might want to investigate. All these are active
-free and open-source software projects at the time of writing.
-</p>
-
-<ul>
-<li><a href='https://hyliu.me/fluent-reader'>Fluent Reader</a> (Linux, Windows, Mac, also mobile I think?)</li>
-<li><a href='https://www.rssowl.org'>RSSOwl</a> (Linux, Windows, Mac)</li>
-<li><a href='https://capyreader.com'>Capy Reader</a> (Android)</li>
-<li><a href='https://apps.kde.org/en-gb/akregator'>Akregator</a> (Linux, Windows (unstable))</li>
-<li><a href='https://gfeeds.gabmus.org'>GFeeds</a> (Linux)</li>
-<li><a href='https://lzone.de/liferea'>Liferea</a> (Linux)</li>
-</ul>
-
-<p>
-For the terminally geeky, there is also
-<a href='https://newsboat.org'>Newsboat</a>. I used it for ages, it works
-fabulously, but it's all in the terminal, so you have to be OK with that.
-</p>
-
-<p>
-You can also just enter 'RSS feed reader' into your favourite search
-engine, software distribution, or app store and see what comes up. Try
-adding 'FOSS' into the query to prioritise free, open-source software.
-</p>
-</section>