Skip to content

Commit

Permalink
Support Front-matter (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
YeungKC authored Jul 10, 2022
1 parent 08d3a1b commit 916524a
Show file tree
Hide file tree
Showing 17 changed files with 181 additions and 102 deletions.
28 changes: 14 additions & 14 deletions .scripts/fetcher.mjs → .scripts/fetcher.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import fetch from 'node-fetch';
import dotenv from 'dotenv';
import { DiscussionsType, FetchDiscussionsType, FetchViewerType } from './types';

dotenv.config();

const fetchData = async (query, variables) => {
const fetchData = async <T>(query: string) => {
const res = await fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
Authorization: `bearer ${process.env.GITHUB_TOKEN}`
},
body: JSON.stringify({
query,
variables
})
body: JSON.stringify({ query })
});

const json = await res.json();
const json: any = await res.json();

if (json.errors) {
throw new Error(JSON.stringify(json.errors, null, 2));
}

return json.data;
return json.data as T;
};

export const fetchUser = async () => {
console.log('fetching... user');
const user = (
await fetchData(`
await fetchData<FetchViewerType>(`
{
viewer {
login
Expand All @@ -39,10 +38,10 @@ export const fetchUser = async () => {
return user;
};

const fetchDiscussions = async (owner, after) => {
export const fetchDiscussions = async (owner: string, after?: string) => {
console.log(`fetching discussions... endCursor: ${after}`);
return (
await fetchData(`
await fetchData<FetchDiscussionsType>(`
{
repository(owner: "${owner}", name: "${process.env.REPOSITORY}") {
discussions(first: 100, ${
Expand All @@ -56,6 +55,7 @@ const fetchDiscussions = async (owner, after) => {
number
title
createdAt
publishedAt
lastEditedAt
url
body
Expand All @@ -77,15 +77,15 @@ const fetchDiscussions = async (owner, after) => {
).repository.discussions;
};

export const fetchAllDiscussions = async (user) => {
export const fetchAllDiscussions = async (user: string) => {
let endCursor;
let list = [];
let list: DiscussionsType[] = [];
// eslint-disable-next-line no-constant-condition
while (true) {
const { nodes, pageInfo } = await fetchDiscussions(user, endCursor);
list = list.concat(nodes);
endCursor = pageInfo.hasNextPage ? pageInfo.endCursor : undefined;
if (!endCursor) break;
if (!pageInfo.hasNextPage) break;
endCursor = pageInfo.endCursor;
}

console.log(`fetched ${list.length} discussions`);
Expand Down
7 changes: 4 additions & 3 deletions .scripts/filter.mjs → .scripts/filter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import dotenv from 'dotenv';
import { DiscussionsType } from './types';
dotenv.config();

const configCategoryName = process.env.CONFIG_CATEGORY || 'Config';
const postCategoryName = process.env.POST_CATEGORY || 'Post';

export const findConfig = (list) => {
export const findConfig = (list: DiscussionsType[]) => {
const configText = list.find(
(e) => e.category.name === configCategoryName && e.title === 'index'
)?.body;
Expand All @@ -14,13 +15,13 @@ export const findConfig = (list) => {
return dotenv.parse(configText);
};

export const filterPage = (list) => {
export const filterPage = (list: DiscussionsType[]) => {
const pages = list.filter((e) => e.category.name === configCategoryName && e.title !== 'index');
console.log(`filtered pages: ${pages.map(({ title }) => title).join(', ')}`);
return pages;
};

export const filterPost = (list) => {
export const filterPost = (list: DiscussionsType[]) => {
const posts = list.filter((e) => e.category.name === postCategoryName);
console.log(`filtered posts: ${posts.length}`);
return posts;
Expand Down
10 changes: 5 additions & 5 deletions .scripts/index.mjs → .scripts/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import dotenv from 'dotenv';
import { fetchUser, fetchAllDiscussions } from './fetcher.mjs';
import { findConfig, filterPage, filterPost } from './filter.mjs';
import { writePosts, writePages, writeEnv } from './writer.mjs';
import { fetchUser, fetchAllDiscussions } from './fetcher.js';
import { findConfig, filterPage, filterPost } from './filter.js';
import { writePosts, writePages, writeEnv } from './writer.js';

dotenv.config();

Expand All @@ -14,7 +14,7 @@ config.NAME = user;
config.BLOG_NAME = config.BLOG_NAME || `${user}'s Blog`;
config.BIO = config.BIO || bio;
config.GITHUB_URL = githubUrl;
config.REPOSITORY = process.env.REPOSITORY;
config.REPOSITORY = process.env.REPOSITORY!;

const pages = filterPage(list);
const posts = filterPost(list);
Expand All @@ -23,6 +23,6 @@ console.log(`writing...`);

await writePosts(posts);
await writePages(pages);
await writeEnv(config, pages);
await writeEnv(config, pages, posts);

console.log(`done`);
39 changes: 39 additions & 0 deletions .scripts/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export interface FetchViewerType {
viewer: {
login: string;
url: string;
bio: string;
};
}

export interface DiscussionsType {
number: number;
title: string;
createdAt: string;
publishedAt: string;
lastEditedAt?: string;
url: string;
body: string;
category: {
name: string;
};
labels: {
nodes: {
name: string;
color: string;
}[];
};
}

export interface PageInfo {
hasNextPage: boolean;
endCursor?: string;
}
export interface FetchDiscussionsType {
repository: {
discussions: {
pageInfo: PageInfo;
nodes: DiscussionsType[];
};
};
}
47 changes: 0 additions & 47 deletions .scripts/writer.mjs

This file was deleted.

48 changes: 48 additions & 0 deletions .scripts/writer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import path from 'path';
import { mkdirSync, promises } from 'fs';
import { DiscussionsType } from './types';
import Post from '../src/lib/types/post';

export const writePosts = async (list: DiscussionsType[]) => {
const dir = path.join('./src/routes/posts/_source');
mkdirSync(dir, { recursive: true });
await Promise.all(
list.map(({ number, body }) => {
const p = path.resolve(dir, `${number}.md`);
return promises.writeFile(p, body);
})
);
};

export const writePages = async (list: DiscussionsType[]) => {
const dir = path.join('./src/routes');
mkdirSync(dir, { recursive: true });
await Promise.all(
list.map(({ title, body }) => {
const p = path.resolve(dir, `${title.toLowerCase()}.md`);
return promises.writeFile(p, body);
})
);
};

export const writeEnv = async (
config: Record<string, string>,
pages: DiscussionsType[],
posts: DiscussionsType[]
) => {
config.PAGES = JSON.stringify(pages.map(({ title }) => title));
config.POSTS = JSON.stringify(
posts.map<Post>((node) => ({
title: node.title,
published: node.publishedAt,
updated: node.lastEditedAt,
number: node.number,
url: node.url,
labels: node.labels.nodes
}))
);
const content = Object.entries(config)
.map(([key, value]) => `VITE_${key}=${value}`)
.join('\n');
return promises.writeFile('./.env.local', content);
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.1",
"scripts": {
"dev": "vite dev",
"generateData": "node .scripts/index.mjs",
"build": "node .scripts/index.mjs && vite build",
"generateData": "ts-node .scripts/index.ts",
"build": "ts-node .scripts/index.ts && vite build",
"package": "svelte-kit package",
"preview": "vite preview",
"prepare": "svelte-kit sync",
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/AboutSection.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import Twitter from '$lib/components/Twitter.svelte';
import { BIO, EMAIL, GITHUB_URL, TWITTER } from '$lib/constants';
let components: any[] = [];
// todo specify type
let components: unknown[] = [];
GITHUB_URL && components.push(Github);
TWITTER && components.push(Twitter);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/PostsSection.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
<ul class="flex flex-col gap-2">
{#each posts as post}
<li class="flex flex-row items-center gap-6">
<div class="shrink-0 text-slate-500">{readableDate(post.createdAt)}</div>
<a class="truncate underline" href={`/posts/${post.discussionNumber}`}>{post.title}</a>
<div class="shrink-0 text-slate-500">{readableDate(post.published)}</div>
<a class="truncate underline" href={`/posts/${post.number}`}>{post.title}</a>
</li>
{/each}
</ul>
6 changes: 5 additions & 1 deletion src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type Post from './types/post';

export const pageSize = 10;

const env = import.meta.env;
Expand All @@ -9,13 +11,15 @@ export const EMAIL = env.VITE_EMAIL;
export const TWITTER = env.VITE_TWITTER;
export const GITHUB_URL = env.VITE_GITHUB_URL;
export const DOMAIN = env.VITE_DOMAIN;
export const PAGES = (env.VITE_PAGES.split(',') as string[])
export const PAGES = (JSON.parse(env.VITE_PAGES) as string[])
.filter((name) => name && name !== '__error')
.map((name) => ({
name,
href: `/${name.toLowerCase()}`
}));

export const POSTS = JSON.parse(env.VITE_POSTS) as Post[];

export const REPOSITORY_URL = `https://github.com/${USER_NAME}/${env.VITE_REPOSITORY}`;
export const REPOSITORY_ISSUES_URL = `${REPOSITORY_URL}/issues`;

Expand Down
32 changes: 26 additions & 6 deletions src/lib/helper/fetchPosts.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import type Post from '$lib/types/post';
import { flatten, countBy, sortBy } from 'lodash-es';
import type { SvelteComponent } from 'svelte';
import { POSTS } from '../constants';

export const fetchPosts = async ({
offset,
limit,
label
}: { offset?: number; limit?: number; label?: string } = {}) => {
let allPosts: Post[] = (
let allPosts = (
await Promise.all(
Object.entries(import.meta.glob(`../../routes/posts/_source/*.md`)).map(
async ([path, page]) => {
const { metadata } = await page();
return metadata;
const { metadata, default: component } = await page();
const number = path.split('/').pop()?.split('.')?.[0];
return {
metadata: {
...POSTS.find((post) => `${post.number}` === number),
metadata
} as Post,
component: component as SvelteComponent
};
}
)
)
).sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
).sort(
(a, b) => new Date(b.metadata.published).valueOf() - new Date(a.metadata.published).valueOf()
);

if (label) {
allPosts = allPosts.filter((post) => post.labels?.includes(label));
allPosts = allPosts.filter((post) =>
post.metadata.labels?.map(({ name }) => name)?.includes(label)
);
}

const count = allPosts.length;
Expand All @@ -40,7 +53,14 @@ export const fetchPosts = async ({
export const fetchLabels = async () => {
const { list } = await fetchPosts();
return sortBy(
Object.entries(countBy(flatten(list.map((e) => e.labels ?? [])))),
Object.entries(
countBy(flatten(list.map((e) => e.metadata.labels?.map(({ name }) => name) ?? [])))
),
([, count]) => -count
);
};

export const fetchPost = async (path: string) => {
const { list } = await fetchPosts();
return list.find(({ metadata: { number } }) => `${number}` === path);
};
2 changes: 2 additions & 0 deletions src/lib/types/post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
'use strict';
exports.__esModule = true;
Loading

0 comments on commit 916524a

Please sign in to comment.