forked from nodejs/nodejs.org
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetBlogData.mjs
More file actions
127 lines (99 loc) · 4.36 KB
/
Copy pathgetBlogData.mjs
File metadata and controls
127 lines (99 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { readFile, readdir } from 'fs/promises';
import { basename, extname, join } from 'path';
import graymatter from 'gray-matter';
import {
getDirectories,
getMatchingRoutes,
getRelativePath,
} from './_helpers.mjs';
// this allows us to get the current module working directory
const __dirname = getRelativePath(import.meta.url);
// gets the current blog path based on local module path
const blogPath = join(__dirname, '../../pages/en/blog');
// gathers only the frontmatter fields that are relevant to us
const getMatter = name => content => {
const { title, author, date, category } = graymatter(content).data;
// we only want the actual name of the file without the extension
// and then prepend the category name to it
const slug = `/blog/${category}/${basename(name, extname(name))}`;
return { title, author, date, category, slug, file: basename(name) };
};
const getPost = category => post =>
readFile(join(blogPath, category, post)).then(getMatter(post));
const getPosts = (category, posts) =>
posts.then(posts => Promise.all(posts.map(getPost(category))));
const currentYear = new Date().getFullYear();
// Note.: This current structure is coupled to the current way how we do pagination and categories
// This will definitely change over time once we start migrating to the `nodejs/nodejs.dev` codebase
const getBlogData = () => {
const blogCategories = getDirectories(blogPath).then(c =>
c.map(s => [s, readdir(join(blogPath, s))])
);
const categoriesPosts = blogCategories.then(c =>
c.map(([s, f]) => [s, getPosts(s, f)])
);
return (route = '/', getAllAvailablePosts = false) => {
const [, , subDirectory, category = `year-${currentYear}`, blogPostSlug] =
route.split('/');
const generatedBlogData = (posts, hasNext, hasPrev) => ({
blogData: {
posts: posts.sort((a, b) => b.date - a.date),
currentCategory: category,
pagination: { next: hasNext || null, prev: hasPrev || null },
},
});
// we don't want to generate blog data within a blog post
if (blogPostSlug && blogPostSlug.length > 0) {
return {};
}
if (getMatchingRoutes(subDirectory, ['blog'])) {
return categoriesPosts.then(categories => {
// yearly pagination posts (doesn't accept category pagination)
if (category && category.startsWith('year-')) {
const selectedYear = Number(category.replace('year-', ''));
// get only the post ingredient from the category array
const allPosts = categories.map(([, f]) => f);
const generatedBlog = posts =>
generatedBlogData(
posts.filter(p => p.date.getFullYear() === selectedYear),
posts.some(p => p.date.getFullYear() === selectedYear + 1) &&
`/blog/year-${selectedYear + 1}`,
posts.some(p => p.date.getFullYear() === selectedYear - 1) &&
`/blog/year-${selectedYear - 1}`
);
return Promise.all(allPosts)
.then(s => Promise.all(s.flat()))
.then(s => s.filter(p => p.date && p.file !== 'index.md'))
.then(generatedBlog);
}
// attempts to find a category that matches the current route category
const currentCategory = categories.find(([c]) => c === category);
if (category && currentCategory) {
// extract the posts part of the current category
const [, categoryPosts] = currentCategory;
const generatedBlog = posts => generatedBlogData(posts);
// get all posts from current category instead of traversing all categories
return categoryPosts
.then(posts => posts.flat())
.then(posts => posts.filter(p => p.file !== 'index.md'))
.then(generatedBlog);
}
// this should not happen or means the category is non-existent
return {};
});
}
if (getAllAvailablePosts) {
return categoriesPosts.then(categories => {
// get only the post ingredient from the category array
const allPosts = categories.map(([, f]) => f);
const generatedBlog = posts => generatedBlogData(posts);
return Promise.all(allPosts)
.then(s => Promise.all(s.flat()))
.then(s => s.filter(p => p.date && p.file !== 'index.md'))
.then(generatedBlog);
});
}
return {};
};
};
export default getBlogData;