Skip to content

Commit cb5a535

Browse files
authored
Release RSS Fix (#456)
* fix start date (#453) * add author and html to rss (#455)
1 parent b8e6d27 commit cb5a535

File tree

8 files changed

+152
-40
lines changed

8 files changed

+152
-40
lines changed

apps/codingcatdev/src/lib/server/content.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { Content, Course } from '$lib/types';
33
import { env } from '$env/dynamic/private';
44
import { fileURLToPath } from 'url';
55
import { opendirSync } from "fs";
6+
import type { SvelteComponentTyped, ComponentType } from 'svelte';
67

78
const LIMIT = 20;
89

@@ -29,45 +30,33 @@ export const getRootPath = (contentType: ContentType, courseDir?: string) => {
2930
return root;
3031
}
3132

32-
export const getContentTypeDirectory = async <T>(contentType: ContentType, courseDir?: string) => {
33+
export const getContentTypeDirectory = async <T>(contentType: ContentType, courseDir?: string, render = false) => {
3334
const contentList: T[] = [];
3435
const dirs = opendirSync(getRootPath(contentType, courseDir));
3536
for await (const dir of dirs) {
3637
if (dir.isFile()) continue;
37-
const parsed = await parseContentType<T>(`${getRootPath(contentType, courseDir)}/${dir.name}/${suffix}`) as T;
38+
const parsed = await parseContentType<T>(`${getRootPath(contentType, courseDir)}/${dir.name}/${suffix}`, render) as T;
3839
contentList.push(parsed);
3940
}
4041
return contentList;
4142
}
4243

43-
export const getContentTypePath = async <T>(contentType: ContentType, path: string, courseDir?: string) => {
44+
export const getContentTypePath = async <T>(contentType: ContentType, path: string, courseDir?: string, render = false) => {
4445
const root = getRootPath(contentType, courseDir);
45-
return await parseContentType<T>(`${root}/${path}/${suffix}`) as T;
46+
return await parseContentType<T>(`${root}/${path}/${suffix}`, render) as T;
4647
}
4748

48-
export const parseContentType = (async <T>(path: string) => {
49-
// If we are in production everything has already been compiled to JavaScript
50-
// and we can just read the metadata, otherwise compile and read.
51-
// let frontmatter;
52-
// let html;
53-
// if (prod) {
54-
const { metadata } = await import(path);
49+
export const parseContentType = (async <T>(path: string, render = false) => {
50+
const { metadata, default: page } = await import(path);
5551
const frontmatter = metadata;
56-
// } else {
57-
// console.log('READ PATH', path);
58-
// const md = readFileSync(path, 'utf8');
59-
// const transformed = await compile(md);
60-
// html = transformed?.code;
61-
// frontmatter = transformed?.data?.fm as Content & Podcast | undefined;
62-
// }
63-
// TODO: Add more checks?
6452

53+
// TODO: Add more checks?
6554
if (!frontmatter?.type) {
6655
console.error('Missing Frontmatter details', path);
6756
return;
6857
}
6958

70-
const content = {
59+
let content = {
7160
...frontmatter,
7261
cover: frontmatter?.cover ? decodeURI(frontmatter?.cover) : '',
7362
type: frontmatter?.type as ContentType,
@@ -77,6 +66,13 @@ export const parseContentType = (async <T>(path: string) => {
7766
slug: path.split('/').at(-2)
7867
};
7968

69+
if (render) {
70+
content = {
71+
...content,
72+
html: page?.render()?.html
73+
}
74+
}
75+
8076
if (frontmatter.type === ContentType.course) {
8177
const lesson = (await listContent<Content>({
8278
contentItems: await getContentTypeDirectory<Content>(ContentType.lesson, frontmatter.slug),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { getContentTypeDirectory, listContent } from '$lib/server/content';
2+
import { ContentType, type Content, type Author } from '$lib/types';
3+
import { buildFeed } from '../rss';
4+
5+
6+
const contentType = ContentType.post;
7+
8+
/** @type {import('./$types').RequestHandler} */
9+
export const GET = async () => {
10+
const contentItems = (await listContent<Content>({
11+
contentItems: await getContentTypeDirectory<Content>(contentType, undefined, true),
12+
limit: 10000
13+
})).content
14+
15+
const authorItems = (await listContent<Author>({
16+
contentItems: await getContentTypeDirectory<Author>(ContentType.author),
17+
limit: 10000
18+
})).content
19+
20+
//xml rss feed response
21+
return new Response(
22+
buildFeed({
23+
contentType, contents: contentItems, authorItems
24+
}).json1(),
25+
{
26+
headers: {
27+
'content-type': 'application/json', 'cache-control': 'max-age=0, s-maxage=3600',
28+
},
29+
}
30+
)
31+
}

apps/codingcatdev/src/routes/(rss)/feed-blog.xml/+server.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getContentTypeDirectory, listContent } from '$lib/server/content';
2-
import { ContentType, type Content } from '$lib/types';
2+
import { ContentType, type Content, type Author } from '$lib/types';
33
import { buildFeed } from '../rss';
44

55

@@ -8,14 +8,19 @@ const contentType = ContentType.post;
88
/** @type {import('./$types').RequestHandler} */
99
export const GET = async () => {
1010
const contentItems = (await listContent<Content>({
11-
contentItems: await getContentTypeDirectory<Content>(ContentType.post),
11+
contentItems: await getContentTypeDirectory<Content>(contentType, undefined, true),
12+
limit: 10000
13+
})).content
14+
15+
const authorItems = (await listContent<Author>({
16+
contentItems: await getContentTypeDirectory<Author>(ContentType.author),
1217
limit: 10000
1318
})).content
1419

1520
//xml rss feed response
1621
return new Response(
1722
buildFeed({
18-
contentType, contents: (await listContent({ contentItems, limit: 10000 })).content
23+
contentType, contents: contentItems, authorItems
1924
}).rss2(),
2025
{
2126
headers: {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { getContentTypeDirectory, listContent } from '$lib/server/content';
2+
import { ContentType, type Content, type Author } from '$lib/types';
3+
import { buildFeed } from '../rss';
4+
5+
6+
const contentType = ContentType.course;
7+
8+
/** @type {import('./$types').RequestHandler} */
9+
export const GET = async () => {
10+
const contentItems = (await listContent<Content>({
11+
contentItems: await getContentTypeDirectory<Content>(contentType, undefined, true),
12+
limit: 10000
13+
})).content
14+
15+
const authorItems = (await listContent<Author>({
16+
contentItems: await getContentTypeDirectory<Author>(ContentType.author),
17+
limit: 10000
18+
})).content
19+
20+
//xml rss feed response
21+
return new Response(
22+
buildFeed({
23+
contentType, contents: contentItems, authorItems
24+
}).json1(),
25+
{
26+
headers: {
27+
'content-type': 'application/json', 'cache-control': 'max-age=0, s-maxage=3600',
28+
},
29+
}
30+
)
31+
}

apps/codingcatdev/src/routes/(rss)/feed-courses.xml/+server.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
import { getContentTypeDirectory, listContent } from '$lib/server/content';
2-
import { ContentType, type Content } from '$lib/types';
2+
import { ContentType, type Content, type Author } from '$lib/types';
33
import { buildFeed } from '../rss';
44

55

6-
const contentType = ContentType.post;
6+
const contentType = ContentType.course;
77

88
/** @type {import('./$types').RequestHandler} */
99
export const GET = async () => {
1010
const contentItems = (await listContent<Content>({
11-
contentItems: await getContentTypeDirectory<Content>(ContentType.course),
11+
contentItems: await getContentTypeDirectory<Content>(contentType, undefined, true),
1212
limit: 10000
1313
})).content
14+
15+
const authorItems = (await listContent<Author>({
16+
contentItems: await getContentTypeDirectory<Author>(ContentType.author),
17+
limit: 10000
18+
})).content
19+
1420
//xml rss feed response
1521
return new Response(
1622
buildFeed({
17-
contentType, contents: (await listContent({ contentItems, limit: 10000 })).content
23+
contentType, contents: contentItems, authorItems
1824
}).rss2(),
1925
{
2026
headers: {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { getContentTypeDirectory, listContent } from '$lib/server/content';
2+
import { ContentType, type Content, type Author } from '$lib/types';
3+
import { buildFeed } from '../rss';
4+
5+
6+
const contentType = ContentType.podcast;
7+
8+
/** @type {import('./$types').RequestHandler} */
9+
export const GET = async () => {
10+
const contentItems = (await listContent<Content>({
11+
contentItems: await getContentTypeDirectory<Content>(contentType, undefined, true),
12+
limit: 10000
13+
})).content
14+
15+
const authorItems = (await listContent<Author>({
16+
contentItems: await getContentTypeDirectory<Author>(ContentType.author),
17+
limit: 10000
18+
})).content
19+
20+
//xml rss feed response
21+
return new Response(
22+
buildFeed({
23+
contentType, contents: contentItems, authorItems
24+
}).json1(),
25+
{
26+
headers: {
27+
'content-type': 'application/json', 'cache-control': 'max-age=0, s-maxage=3600',
28+
},
29+
}
30+
)
31+
}

apps/codingcatdev/src/routes/(rss)/feed-podcasts.xml/+server.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
import { getContentTypeDirectory, listContent } from '$lib/server/content';
2-
import { ContentType, type Content } from '$lib/types';
2+
import { ContentType, type Content, type Author } from '$lib/types';
33
import { buildFeed } from '../rss';
44

55

6-
const contentType = ContentType.post;
6+
const contentType = ContentType.podcast;
77

88
/** @type {import('./$types').RequestHandler} */
99
export const GET = async () => {
1010
const contentItems = (await listContent<Content>({
11-
contentItems: await getContentTypeDirectory<Content>(ContentType.podcast),
11+
contentItems: await getContentTypeDirectory<Content>(contentType, undefined, true),
12+
limit: 10000
13+
})).content
14+
15+
const authorItems = (await listContent<Author>({
16+
contentItems: await getContentTypeDirectory<Author>(ContentType.author),
1217
limit: 10000
1318
})).content
1419

1520
//xml rss feed response
1621
return new Response(
1722
buildFeed({
18-
contentType, contents: (await listContent({ contentItems, limit: 10000 })).content
23+
contentType, contents: contentItems, authorItems
1924
}).rss2(),
2025
{
2126
headers: {

apps/codingcatdev/src/routes/(rss)/rss.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import type { Content, ContentType } from "$lib/types";
2-
import { Feed } from 'feed';
1+
import type { Content, ContentType, Author } from "$lib/types";
2+
import { Feed, type Author as FeedAuthor } from 'feed';
33

44
const site = 'https://codingcat.dev';
55

66

77
export const buildFeed = ({
88
contents,
99
contentType,
10+
authorItems,
1011
}: {
1112
contents: Content[];
1213
contentType: ContentType;
14+
authorItems: Author[];
1315
}) => {
1416
const feed = new Feed({
1517
title: `${site} - ${contentType} feed`,
@@ -32,22 +34,27 @@ export const buildFeed = ({
3234
});
3335

3436
for (const content of contents) {
37+
38+
const authors = content?.authors?.map((authorSlug) => {
39+
return authorItems.filter(a => a.slug === authorSlug).map(a => {
40+
return {
41+
name: a.name,
42+
link: `${site}/author/${a.slug}`,
43+
}
44+
})?.at(0) as FeedAuthor;
45+
}).filter(a => a !== undefined)
3546
feed.addItem({
3647
title: content.title || '',
48+
content: content.html,
3749
link: `${site}/${contentType}/${content.slug}`,
3850
description: `${content.excerpt}`,
3951
image: content.cover || feed.items.at(0)?.image,
4052
date: content.start || new Date(),
41-
author: content?.authors ? content.authors?.map((author) => {
42-
return {
43-
name: author.name,
44-
link: `${site}/authors/${author.slug}`,
45-
};
46-
})
53+
author: authors ? authors
4754
: [{
4855
name: 'Alex Patterson',
4956
email: 'alex@codingcat.dev',
50-
link: `${site}`,
57+
link: `${site}/author/alex-patterson`,
5158
}],
5259
});
5360
}

0 commit comments

Comments
 (0)