summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorJoe Carstairs <65492573+Sycamost@users.noreply.github.com>2024-03-30 16:32:17 +0000
committerJoe Carstairs <65492573+Sycamost@users.noreply.github.com>2024-03-30 16:43:22 +0000
commit261d89ebed13691e72312f44339063fee93130ac (patch)
tree43cb6f1a9804352f666efaaee2bf7d6189906f08 /src/components
parent9cb047768f79f3d14a5c6bcf420e76d600a20f2d (diff)
Astro initial commit
Diffstat (limited to 'src/components')
-rw-r--r--src/components/BaseHead.astro44
-rw-r--r--src/components/BlogFeed.astro76
-rw-r--r--src/components/FormattedDate.astro21
-rw-r--r--src/components/Me.astro43
4 files changed, 184 insertions, 0 deletions
diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro
new file mode 100644
index 0000000..e8e44ab
--- /dev/null
+++ b/src/components/BaseHead.astro
@@ -0,0 +1,44 @@
+---
+interface Props {
+ title: string;
+ description: string;
+ image?: string;
+}
+
+const canonicalURL = new URL(Astro.url.pathname, Astro.site);
+
+const { title, description, image = '/images/headshot.jpg' } = Astro.props;
+---
+
+<!-- Stylesheets -->
+<link rel="stylesheet" href="/css/reset.css" />
+<link rel="stylesheet" href="/css/base.css" />
+<link rel="stylesheet" href="/css/hcard.css" />
+
+<!-- Global Metadata -->
+<meta charset="utf-8" />
+<meta name="viewport" content="width=device-width,initial-scale=1" />
+<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+<meta name="generator" content={Astro.generator} />
+
+<!-- Canonical URL -->
+<link rel="canonical" href={canonicalURL} />
+
+<!-- Primary Meta Tags -->
+<title>{title}</title>
+<meta name="title" content={title} />
+<meta name="description" content={description} />
+
+<!-- Open Graph / Facebook -->
+<meta property="og:type" content="website" />
+<meta property="og:url" content={Astro.url} />
+<meta property="og:title" content={title} />
+<meta property="og:description" content={description} />
+<meta property="og:image" content={new URL(image, Astro.url)} />
+
+<!-- Twitter -->
+<meta property="twitter:card" content="summary_large_image" />
+<meta property="twitter:url" content={Astro.url} />
+<meta property="twitter:title" content={title} />
+<meta property="twitter:description" content={description} />
+<meta property="twitter:image" content={new URL(image, Astro.url)} />
diff --git a/src/components/BlogFeed.astro b/src/components/BlogFeed.astro
new file mode 100644
index 0000000..d785524
--- /dev/null
+++ b/src/components/BlogFeed.astro
@@ -0,0 +1,76 @@
+---
+import type { CollectionEntry } from 'astro:content';
+import { getCollection } from 'astro:content';
+
+export interface Props {
+ headingLevel?: 1 | 2 | 3 | 4 | 5 | 6,
+ hideAuthor?: boolean,
+};
+
+const { headingLevel = 2, hideAuthor = false } = Astro.props;
+
+const posts = (await getCollection('blog'));
+
+const distinctYears: number[] = posts
+ .map(post => post.data.pubDate.year)
+ .reduce<number[]>((acc, curr) => acc.includes(curr) ? acc : [...acc, curr], [])
+ .sort((a, b) => b - a);
+
+function matchesYear(year: number) {
+ return (post: CollectionEntry<'blog'>) => post.data.pubDate.year === year;
+}
+
+function sortByPubDateDescending(post1: CollectionEntry<'blog'>, post2: CollectionEntry<'blog'>) {
+ const year1 = post1.data.pubDate.year;
+ const year2 = post2.data.pubDate.year;
+ const month1 = post1.data.pubDate.month;
+ const month2 = post2.data.pubDate.month;
+ const day1 = post1.data.pubDate.day;
+ const day2 = post2.data.pubDate.day;
+
+ if (year1 !== year2) {
+ return year2 - year1;
+ } else if (month1 !== month2) {
+ return month2 - month1;
+ } else {
+ return day2 - day1;
+ }
+}
+
+const headingElem = `h${headingLevel}`;
+
+const canonicalUrl = new URL(Astro.url.pathname, Astro.site)
+---
+
+<section class="h-feed">
+ <Fragment set:html={`
+ <${headingElem} class="p-name">
+ My blog
+ </${headingElem}>
+ `} />
+
+ <aside>
+ <p class={hideAuthor ? 'hidden' : ''}>
+ This blog is written by <a class="p-author h-card" href="/">Joe Carstairs</a>
+ </p>
+
+ <p>
+ <a class="u-url" href={canonicalUrl}>Permalink</a>
+ </p>
+ </aside>
+
+ <ul>
+ { distinctYears.map(year => (
+ <li>
+ {year}
+ <ul>
+ { posts.filter(matchesYear(year)).sort(sortByPubDateDescending).map(post => (
+ <li class="h-entry">
+ <a class="u-url p-name" href={`/blog/${post.slug}`}>{post.data.title}</a>
+ </li>
+ )) }
+ </ul>
+ </li>
+ )) }
+ </ul>
+</section> \ No newline at end of file
diff --git a/src/components/FormattedDate.astro b/src/components/FormattedDate.astro
new file mode 100644
index 0000000..bb7a2c0
--- /dev/null
+++ b/src/components/FormattedDate.astro
@@ -0,0 +1,21 @@
+---
+interface Props {
+ className?: string;
+ date: Date | string;
+}
+
+let { className, date } = Astro.props;
+if (typeof(date) === 'string') {
+ date = new Date(date);
+}
+---
+
+<time datetime={date.toISOString()} class={className ?? ''}>
+ {
+ date.toLocaleDateString('en-GB', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ })
+ }
+</time>
diff --git a/src/components/Me.astro b/src/components/Me.astro
new file mode 100644
index 0000000..c9af587
--- /dev/null
+++ b/src/components/Me.astro
@@ -0,0 +1,43 @@
+---
+---
+
+<section class="h-card">
+ <img class="u-photo" src="/images/headshot.jpg" height="256" width="256" />
+
+ <div>
+ <h1>
+ <a class="p-name u-url u-uid" href="https://joeac.net" rel="me">
+ Joe Carstairs
+ </a>
+ </h1>
+
+ <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
+ graduate of Philosophy and Mathematics at the University of Edinburgh,
+ a committed Christian and a pretty rubbish poet.
+ </p>
+
+ <p>
+ I’m also the <span class="p-job-title">secretary</span> of the
+ <a class="p-org" href="https://scotsleidassocie.org">Scots Language Society</a>.
+ <a href="https://github.com/joeacarstairs/lallans-wabsteid-astro">Help me maintain our website!</a>
+ </p>
+
+ <p>
+ Email me at
+ <a class="u-email" href="mailto:joeacarstairs@gmail.com">joeacarstairs@gmail.com</a>
+ with your thoughts on metaethics, Scots verse and eschatology.
+ </p>
+
+ <p>
+ 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>,
+ or <a href="https://github.com/joeacarstairs" rel="me">GitHub</a>.
+ </p>
+ </div>
+</section> \ No newline at end of file