Skip to content

Commit 650532c

Browse files
committed
feat: added support for multiple coauthors for blogs in appwrite
1 parent 8fa54fa commit 650532c

File tree

7 files changed

+122
-49
lines changed

7 files changed

+122
-49
lines changed

src/lib/components/blog/post-meta.svelte

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
timeToRead?: string;
1111
title?: string;
1212
description?: string;
13-
authorData?: Partial<AuthorData>;
13+
authorData?: Partial<AuthorData> | Partial<AuthorData>[];
1414
currentURL?: string;
1515
}
1616
@@ -23,6 +23,10 @@
2323
currentURL = ''
2424
}: Props = $props();
2525
26+
const authorsArray = $derived(
27+
Array.isArray(authorData) ? authorData : authorData ? [authorData] : []
28+
);
29+
2630
const getShareLink = (shareOption: SocialShareOption) => {
2731
const blogPostUrl = encodeURI(currentURL);
2832
return shareOption.link.replace('{TITLE}', title + '.').replace('{URL}', blogPostUrl);
@@ -49,25 +53,33 @@
4953
</div>
5054

5155
<div class="border-smooth mb-8 flex flex-col justify-between border-b py-8 md:flex-row">
52-
{#if authorData}
53-
<a href={authorData.href} class="flex items-center gap-2">
54-
{#if authorData.avatar}
55-
<img
56-
class="size-11 rounded-full"
57-
src={authorData.avatar}
58-
alt={authorData.name}
59-
loading="lazy"
60-
width="44"
61-
height="44"
62-
/>
63-
{/if}
64-
<div class="flex flex-col">
65-
<h4 class="text-sub-body text-primary">
66-
{authorData.name}
67-
</h4>
68-
<p class="text-caption">{authorData.role}</p>
69-
</div>
70-
</a>
56+
{#if authorsArray.length > 0}
57+
<div class="flex flex-wrap items-center gap-4">
58+
{#each authorsArray as author}
59+
{#if author}
60+
<a href={author.href} class="flex items-center gap-2">
61+
{#if author.avatar}
62+
<img
63+
class="size-11 rounded-full"
64+
src={author.avatar}
65+
alt={author.name || ''}
66+
loading="lazy"
67+
width="44"
68+
height="44"
69+
/>
70+
{/if}
71+
<div class="flex flex-col">
72+
<h4 class="text-sub-body text-primary">
73+
{author.name}
74+
</h4>
75+
{#if author.role}
76+
<p class="text-caption">{author.role}</p>
77+
{/if}
78+
</div>
79+
</a>
80+
{/if}
81+
{/each}
82+
</div>
7183
{/if}
7284

7385
<div class="mt-4 flex items-center gap-4">

src/lib/utils/metadata.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,23 @@ export function softwareAppSchema() {
7070
*/
7171
export function createPostSchema(
7272
post: { title: string; cover: string; date: string; lastUpdated?: string },
73-
author?: AuthorData
73+
authors?: AuthorData | AuthorData[]
7474
) {
75+
const authorsArray = Array.isArray(authors) ? authors : authors ? [authors] : [];
76+
7577
return JSON.stringify({
7678
'@context': 'https://schema.org',
7779
'@type': 'BlogPosting',
7880
headline: post.title,
7981
image: [post.cover],
8082
datePublished: post.date,
8183
...(post.lastUpdated && { dateModified: post.lastUpdated }),
82-
...(author && {
83-
author: [
84-
{
85-
'@type': 'Person',
86-
url: author.href,
87-
name: author.name
88-
}
89-
]
84+
...(authorsArray.length > 0 && {
85+
author: authorsArray.map((author) => ({
86+
'@type': 'Person',
87+
url: author.href,
88+
name: author.name
89+
}))
9090
})
9191
});
9292
}

src/markdoc/layouts/Author.svelte

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,24 @@
169169

170170
<div class="mt-12">
171171
<ul class="web-grid-articles">
172-
{#each posts.filter((p) => p.author === author?.slug) as post}
172+
{#each posts.filter( (p) => (Array.isArray(p.author) ? p.author.includes(author?.slug ?? '') : p.author === author?.slug) ) as post}
173+
{@const postAuthorSlugs = Array.isArray(post.author)
174+
? post.author
175+
: [post.author]}
176+
{@const primaryAuthor =
177+
authors.find((a) => postAuthorSlugs.includes(a.slug)) ?? author}
178+
{@const authorNames = postAuthorSlugs
179+
.map((slug) => authors.find((a) => a.slug === slug)?.name)
180+
.filter(Boolean)
181+
.join(', ')}
173182
<Article
174183
title={post.title}
175184
href={post.href}
176185
cover={post.cover}
177186
date={post.date}
178187
timeToRead={post.timeToRead}
179-
{avatar}
180-
author={name}
188+
avatar={primaryAuthor?.avatar ?? avatar}
189+
author={authorNames || primaryAuthor?.name || name}
181190
/>
182191
{/each}
183192
</ul>

src/markdoc/layouts/Category.svelte

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,29 @@
5858
<div class="mt-12">
5959
<ul class="web-grid-articles">
6060
{#each posts as post}
61-
{@const author = authors.find((a) => a.slug.includes(post.author))}
61+
{@const postAuthorSlugs = Array.isArray(post.author)
62+
? post.author
63+
: [post.author]}
64+
{@const primarySlug = postAuthorSlugs[0]}
65+
{@const author =
66+
authors.find((a) => a.slug === primarySlug) ||
67+
authors.find((a) => postAuthorSlugs.includes(a.slug))}
6268
{#if author}
69+
{@const authorNames = postAuthorSlugs
70+
.map((slug) => authors.find((a) => a.slug === slug)?.name)
71+
.filter(Boolean)}
72+
{@const authorLabel =
73+
authorNames.length > 1
74+
? `${authorNames[0]} +${authorNames.length - 1}`
75+
: authorNames[0] || author.name}
6376
<Article
6477
title={post.title}
6578
href={post.href}
6679
cover={post.cover}
6780
date={post.date}
6881
timeToRead={post.timeToRead}
6982
avatar={author.avatar}
70-
author={author.name}
83+
author={authorLabel}
7184
/>
7285
{/if}
7386
{/each}

src/markdoc/layouts/Post.svelte

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
2929
export let title: string;
3030
export let description: string;
31-
export let author: string;
31+
export let author: string | string[];
3232
export let date: string;
3333
export let timeToRead: string;
3434
export let cover: string;
@@ -40,7 +40,10 @@
4040
(post) => !(post.unlisted ?? false) && !(post.draft ?? false)
4141
);
4242
const authors = getContext<AuthorData[]>('authors');
43-
const authorData = authors.find((a) => a.slug === author);
43+
const authorSlugs = Array.isArray(author) ? author : [author];
44+
const authorData = authorSlugs
45+
.map((slug) => authors.find((a) => a.slug === slug))
46+
.filter((a): a is AuthorData => a !== undefined);
4447
4548
setContext<LayoutContext>('headings', writable({}));
4649
@@ -135,7 +138,11 @@
135138
date: date,
136139
lastUpdated: lastUpdated
137140
},
138-
authorData
141+
authorData.length > 0
142+
? authorData.length === 1
143+
? authorData[0]
144+
: authorData
145+
: undefined
139146
)
140147
)}
141148
</svelte:head>
@@ -184,16 +191,29 @@
184191
<section class="mt-8">
185192
<div class="grid grid-cols-1 gap-12 md:grid-cols-3">
186193
{#each posts.filter((p) => p.title !== title).slice(0, 3) as post}
187-
{@const author = authors.find((a) => a.slug === post.author)}
188-
{#if author}
194+
{@const postAuthorSlugs = Array.isArray(post.author)
195+
? post.author
196+
: [post.author]}
197+
{@const primarySlug = postAuthorSlugs[0]}
198+
{@const postAuthor =
199+
authors.find((a) => a.slug === primarySlug) ||
200+
authors.find((a) => postAuthorSlugs.includes(a.slug))}
201+
{#if postAuthor}
202+
{@const authorNames = postAuthorSlugs
203+
.map((slug) => authors.find((a) => a.slug === slug)?.name)
204+
.filter(Boolean)}
205+
{@const authorLabel =
206+
authorNames.length > 1
207+
? `${authorNames[0]} +${authorNames.length - 1}`
208+
: authorNames[0] || postAuthor.name}
189209
<Article
190210
title={post.title}
191211
href={post.href}
192212
cover={post.cover}
193213
date={post.date}
194214
timeToRead={post.timeToRead}
195-
avatar={author.avatar}
196-
author={author.name}
215+
avatar={postAuthor.avatar}
216+
author={authorLabel}
197217
/>
198218
{/if}
199219
{/each}

src/routes/blog/[[page]]/+page.svelte

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,15 @@
212212
<div class="container">
213213
<h1 class="text-display font-aeonik-pro text-primary">Blog</h1>
214214
{#if featured}
215-
{@const author = data.authors.find(
216-
(author) => author.slug === featured.author
217-
)}
215+
{@const featuredAuthorSlugs = Array.isArray(featured.author)
216+
? featured.author
217+
: [featured.author]}
218+
{@const featuredPrimarySlug = featuredAuthorSlugs[0]}
219+
{@const author =
220+
data.authors.find((author) => author.slug === featuredPrimarySlug) ||
221+
data.authors.find((author) =>
222+
featuredAuthorSlugs.includes(author.slug)
223+
)}
218224
<article class="web-feature-article mt-12">
219225
<a
220226
href={featured.href}
@@ -371,18 +377,31 @@
371377
<div class="mt-12">
372378
<ul class:web-grid-articles={data.posts.length > 0}>
373379
{#each data.posts as post (post.slug)}
374-
{@const author = data.authors.find(
375-
(author) => author.slug === post.author
376-
)}
380+
{@const postAuthorSlugs = Array.isArray(post.author)
381+
? post.author
382+
: [post.author]}
383+
{@const primarySlug = postAuthorSlugs[0]}
384+
{@const author =
385+
data.authors.find((author) => author.slug === primarySlug) ||
386+
data.authors.find((author) =>
387+
postAuthorSlugs.includes(author.slug)
388+
)}
377389
{#if author && !post.draft}
390+
{@const authorNames = postAuthorSlugs
391+
.map((slug) => data.authors.find((a) => a.slug === slug)?.name)
392+
.filter(Boolean)}
393+
{@const authorLabel =
394+
authorNames.length > 1
395+
? `${authorNames[0]} +${authorNames.length - 1}`
396+
: authorNames[0] || author.name}
378397
<Article
379398
title={post.title}
380399
href={post.href}
381400
cover={post.cover}
382401
date={post.date}
383402
timeToRead={post.timeToRead}
384403
avatar={author.avatar}
385-
author={author.name}
404+
author={authorLabel}
386405
/>
387406
{/if}
388407
{:else}

src/routes/blog/content.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface PostsData {
2525
lastUpdated: Date;
2626
cover: string;
2727
timeToRead: number;
28-
author: string;
28+
author: string | string[];
2929
category: string;
3030
href: string;
3131
slug: string;

0 commit comments

Comments
 (0)