diff options
Diffstat (limited to 'http/src')
| -rw-r--r-- | http/src/blog.upphtml | 76 | ||||
| -rw-r--r-- | http/src/blog/rss.uppxml | 50 | ||||
| -rw-r--r-- | http/src/blog/subscribe.trivial.upphtml | 4 | ||||
| -rw-r--r-- | http/src/contact.upphtml | 96 | ||||
| -rw-r--r-- | http/src/css/base.uppcss | 515 | ||||
| -rw-r--r-- | http/src/css/feed.uppcss | 45 | ||||
| -rw-r--r-- | http/src/css/hcard.uppcss | 57 | ||||
| -rw-r--r-- | http/src/css/otp.uppcss | 29 | ||||
| -rw-r--r-- | http/src/css/post.uppcss | 8 | ||||
| -rw-r--r-- | http/src/css/reset.uppcss | 93 | ||||
| -rw-r--r-- | http/src/error.upphtml | 14 | ||||
| -rw-r--r-- | http/src/index.upphtml | 47 | ||||
| -rw-r--r-- | http/src/links/rss.trivial.upphtml | 4 | ||||
| -rw-r--r-- | http/src/microlog.upphtml | 84 | ||||
| -rw-r--r-- | http/src/microlog/rss.uppxml | 50 | ||||
| -rw-r--r-- | http/src/sitemap.uppxml | 21 | ||||
| -rw-r--r-- | http/src/subscribe.upphtml | 91 |
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/&/\\&/g" \ - | sed "s/</\\</g" \ - | sed "s/>/\\>/g" \ - | sed "s/\"/\\"/g" \ - | sed "s/'/\\'/g" \ - | sed "s/\`/\\`/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/&/\\&/g" \ - | sed "s/</\\</g" \ - | sed "s/>/\\>/g" \ - | sed "s/\"/\\"/g" \ - | sed "s/'/\\'/g" \ - | sed "s/\`/\\`/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> |
