1
00:00:02,000 --> 00:00:05,000
So now we wanna use our markdown files

2
00:00:05,000 --> 00:00:07,000
in the posts folder as a data source.

3
00:00:07,000 --> 00:00:09,000
For example, for the starting page here,

4
00:00:09,000 --> 00:00:13,000
instead of using dummy posts, we wanna fetch our posts

5
00:00:13,000 --> 00:00:15,000
from that post folder,

6
00:00:15,000 --> 00:00:19,000
for example with help of get started props.

7
00:00:19,000 --> 00:00:20,000
Now, before we do that,

8
00:00:20,000 --> 00:00:24,000
I'll first of all create a new folder in the project though,

9
00:00:24,000 --> 00:00:27,000
a lib folder or helpers folder,

10
00:00:27,000 --> 00:00:28,000
whatever you wanna call it.

11
00:00:28,000 --> 00:00:32,000
And in there, I'll add posts-util.js file.

12
00:00:36,000 --> 00:00:37,000
This simply is a file

13
00:00:37,000 --> 00:00:40,000
which will have extra utility functionality

14
00:00:40,000 --> 00:00:42,000
for fetching my post data

15
00:00:42,000 --> 00:00:47,000
and for extracting metadata from those markdown files.

16
00:00:47,000 --> 00:00:49,000
And speaking off that,

17
00:00:49,000 --> 00:00:52,000
for this we need to install another extra package.

18
00:00:52,000 --> 00:00:54,000
So quit your running development server

19
00:00:54,000 --> 00:00:58,000
and install an extra package with npm install.

20
00:00:58,000 --> 00:01:02,000
And that would be the gray-matter package.

21
00:01:02,000 --> 00:01:06,000
That's a package which allows us to read a markdown file

22
00:01:06,000 --> 00:01:11,000
and split it into metadata and the actual markdown content.

23
00:01:12,000 --> 00:01:13,000
Once that's installed,

24
00:01:13,000 --> 00:01:16,000
we can start the development server again.

25
00:01:16,000 --> 00:01:19,000
And now in posts-util.js,

26
00:01:19,000 --> 00:01:23,000
I wanna add a couple of functions that fetch us all posts,

27
00:01:23,000 --> 00:01:27,000
all featured posts and then also a single post.

28
00:01:30,000 --> 00:01:32,000
Now let's maybe start with all posts.

29
00:01:32,000 --> 00:01:36,000
Let's add a getAllPosts function here.

30
00:01:36,000 --> 00:01:39,000
The idea here is that we take a look

31
00:01:39,000 --> 00:01:43,000
at this posts folder with the markdown files

32
00:01:43,000 --> 00:01:47,000
and simply check how many markdown files we have there

33
00:01:47,000 --> 00:01:50,000
and then go through all those markdown files

34
00:01:50,000 --> 00:01:53,000
to get the metadata for all those files.

35
00:01:53,000 --> 00:01:56,000
Now for going through all those files here,

36
00:01:56,000 --> 00:01:59,000
I will work with the file system

37
00:01:59,000 --> 00:02:03,000
and hence we should import fs from fs.

38
00:02:03,000 --> 00:02:06,000
So import does fs node module.

39
00:02:07,000 --> 00:02:09,000
And then here in getAllPosts,

40
00:02:09,000 --> 00:02:12,000
I'll start by reading all the content from a directory,

41
00:02:12,000 --> 00:02:17,000
with the fs module and the readdirSync method,

42
00:02:17,000 --> 00:02:20,000
readdirSync will read all the contents synchronously.

43
00:02:20,000 --> 00:02:23,000
So in a blocking way, which is fine here,

44
00:02:23,000 --> 00:02:25,000
because I wanna parse all posts anyways

45
00:02:25,000 --> 00:02:27,000
before I do anything else.

46
00:02:27,000 --> 00:02:30,000
So I'll read the entire content off a directory

47
00:02:30,000 --> 00:02:32,000
in one go here.

48
00:02:32,000 --> 00:02:34,000
Now we need to pass a path

49
00:02:34,000 --> 00:02:37,000
to the directory to readdirSync.

50
00:02:37,000 --> 00:02:38,000
And I'll create this

51
00:02:38,000 --> 00:02:43,000
as a separate constant outside of all those functions here.

52
00:02:43,000 --> 00:02:45,000
I'll name it postsDirectory,

53
00:02:45,000 --> 00:02:47,000
though of course, the name is up to you.

54
00:02:47,000 --> 00:02:52,000
And then here, I'll import another thing from node JS.

55
00:02:52,000 --> 00:02:55,000
I'll import the path module here.

56
00:02:55,000 --> 00:02:58,000
This allows me to construct an absolute path,

57
00:02:58,000 --> 00:03:00,000
with the join method.

58
00:03:01,000 --> 00:03:05,000
And here I join process.current working directory,

59
00:03:05,000 --> 00:03:06,000
executed as a method,

60
00:03:06,000 --> 00:03:10,000
which will point at the overall project folder,

61
00:03:10,000 --> 00:03:13,000
as you learned, not at this lib folder,

62
00:03:13,000 --> 00:03:15,000
but at the overall project folder.

63
00:03:15,000 --> 00:03:17,000
So that is then an absolute path

64
00:03:17,000 --> 00:03:20,000
to the overall project folder,

65
00:03:20,000 --> 00:03:22,000
and then I'll add posts

66
00:03:22,000 --> 00:03:25,000
as an extra folder into which it should dive.

67
00:03:25,000 --> 00:03:27,000
So this posts folder here.

68
00:03:29,000 --> 00:03:33,000
That's then an absolute path to my posts directory

69
00:03:33,000 --> 00:03:35,000
and that's the directory I wanna read.

70
00:03:35,000 --> 00:03:38,000
So that's what I pass to readdirSync.

71
00:03:39,000 --> 00:03:44,000
Now this will return an array of strings, as you see.

72
00:03:45,000 --> 00:03:48,000
In the end, it will be an array of file names.

73
00:03:48,000 --> 00:03:50,000
So here I have my postFiles

74
00:03:51,000 --> 00:03:53,000
which are load with readdirSync.

75
00:03:54,000 --> 00:03:55,000
As a next step,

76
00:03:55,000 --> 00:03:59,000
I now wanna go through all those post files and dive

77
00:03:59,000 --> 00:04:03,000
into them to extract metadata and markdown content.

78
00:04:04,000 --> 00:04:06,000
I also wanna derive a slug

79
00:04:06,000 --> 00:04:10,000
which can be put in the URL from the file name.

80
00:04:10,000 --> 00:04:12,000
So basically I wanna use the file name,

81
00:04:12,000 --> 00:04:15,000
without the extension, which still is part inside

82
00:04:15,000 --> 00:04:17,000
of postFiles at the moment.

83
00:04:18,000 --> 00:04:21,000
Now for this I'll add an extra helper function,

84
00:04:21,000 --> 00:04:25,000
getPostData, sounds like a fitting name.

85
00:04:25,000 --> 00:04:29,000
And here I expect to get the file name as an argument.

86
00:04:29,000 --> 00:04:33,000
Now in getPostData, we wanna read the content of a file.

87
00:04:33,000 --> 00:04:36,000
We can again do that with the fs module.

88
00:04:36,000 --> 00:04:40,000
And there, we have that readFileSync method

89
00:04:40,000 --> 00:04:42,000
for reading the content of a file.

90
00:04:42,000 --> 00:04:45,000
Here, we need the fileName, but not just the fileName,

91
00:04:45,000 --> 00:04:49,000
we still need the full path to that file.

92
00:04:49,000 --> 00:04:53,000
So I'll construct my file path here

93
00:04:53,000 --> 00:04:57,000
by again using path.join

94
00:04:57,000 --> 00:05:00,000
and I'll join this posts directory path with

95
00:05:00,000 --> 00:05:04,000
which we already have, with that file name.

96
00:05:04,000 --> 00:05:07,000
So that constructs a full absolute path

97
00:05:07,000 --> 00:05:08,000
to that concrete file.

98
00:05:09,000 --> 00:05:12,000
Now we can use this filePath

99
00:05:12,000 --> 00:05:14,000
for reading the content of that file.

100
00:05:14,000 --> 00:05:17,000
We can always add a second argument here

101
00:05:17,000 --> 00:05:20,000
and make it clear that the file encoding is UTF-8

102
00:05:20,000 --> 00:05:23,000
so that we support all those Unicode characters.

103
00:05:25,000 --> 00:05:28,000
Then we got the file content here.

104
00:05:28,000 --> 00:05:30,000
That's what readFileSync produces.

105
00:05:31,000 --> 00:05:34,000
Now we're doing this for a single file here.

106
00:05:34,000 --> 00:05:36,000
So I'm not doing this in a loop or anything like this.

107
00:05:36,000 --> 00:05:38,000
I'm just doing this for one file.

108
00:05:38,000 --> 00:05:41,000
We're going to call getPostData

109
00:05:41,000 --> 00:05:44,000
in a loop for all files later, though.

110
00:05:45,000 --> 00:05:47,000
But here we then have to content all the single file.

111
00:05:47,000 --> 00:05:49,000
And now we know that in a single file,

112
00:05:49,000 --> 00:05:53,000
we have this metadata and the actual content.

113
00:05:53,000 --> 00:05:57,000
Now the overall content is what node JS extracted for us.

114
00:05:57,000 --> 00:05:58,000
To split it up,

115
00:05:58,000 --> 00:06:02,000
we'll use this gray matter package which we installed.

116
00:06:02,000 --> 00:06:07,000
So for this I'll import matter from gray-matter, like this.

117
00:06:08,000 --> 00:06:10,000
And matter is simply a function

118
00:06:10,000 --> 00:06:15,000
which we can call here to which we pass a string.

119
00:06:15,000 --> 00:06:18,000
And our file content is just a string.

120
00:06:18,000 --> 00:06:21,000
It's the content of a file as text.

121
00:06:21,000 --> 00:06:24,000
So we pass the file content to matter,

122
00:06:24,000 --> 00:06:28,000
and matter will then return an object with two properties,

123
00:06:28,000 --> 00:06:32,000
with a data property for the metadata.

124
00:06:32,000 --> 00:06:34,000
So a data property, which contains the metadata

125
00:06:34,000 --> 00:06:39,000
as a JavaScript object and a content property

126
00:06:39,000 --> 00:06:41,000
which contains the actual content,

127
00:06:41,000 --> 00:06:44,000
the markdown text as a string.

128
00:06:44,000 --> 00:06:46,000
So we can use object destructuring

129
00:06:46,000 --> 00:06:49,000
to pull these two properties out of the returned object

130
00:06:49,000 --> 00:06:54,000
and store them in separate constants, data and content.

131
00:06:54,000 --> 00:06:55,000
And these names are not up to you,

132
00:06:55,000 --> 00:07:00,000
these are the properties in that object created by matter.

133
00:07:00,000 --> 00:07:02,000
So by this matter function.

134
00:07:03,000 --> 00:07:04,000
Now that we got that,

135
00:07:04,000 --> 00:07:09,000
we can prepare our own postData object

136
00:07:10,000 --> 00:07:14,000
which should contain all that metadata and that content,

137
00:07:14,000 --> 00:07:18,000
but also contain an extra select field with the slug,

138
00:07:18,000 --> 00:07:21,000
so with the file name, without the file extension.

139
00:07:22,000 --> 00:07:25,000
For this I'll first of all, create my post slug here

140
00:07:25,000 --> 00:07:30,000
and we can easily create this by using our file name

141
00:07:30,000 --> 00:07:35,000
and simply replacing the file extension with nothing.

142
00:07:35,000 --> 00:07:37,000
We could use a regular expression here

143
00:07:37,000 --> 00:07:40,000
to select the markdown extension,

144
00:07:40,000 --> 00:07:42,000
with this regular expression

145
00:07:42,000 --> 00:07:45,000
and replace it with an empty string.

146
00:07:45,000 --> 00:07:49,000
So this removes the file extension in the end,

147
00:07:49,000 --> 00:07:51,000
that leaves us with a slug

148
00:07:51,000 --> 00:07:54,000
which is just a file name without the extension.

149
00:07:54,000 --> 00:07:56,000
And therefore, of course, you should make sure

150
00:07:56,000 --> 00:08:00,000
that your file names do have this slug format

151
00:08:00,000 --> 00:08:05,000
and do not contain any special characters or white space.

152
00:08:05,000 --> 00:08:06,000
And once that's done,

153
00:08:06,000 --> 00:08:09,000
we can prepare that post data which we return.

154
00:08:09,000 --> 00:08:11,000
Here, I wanna add a slug field

155
00:08:11,000 --> 00:08:14,000
and store my created post slug.

156
00:08:14,000 --> 00:08:17,000
I will then also spread my data in there.

157
00:08:17,000 --> 00:08:21,000
So the data we extract it from the markdown file

158
00:08:21,000 --> 00:08:23,000
and I'll add a content field

159
00:08:23,000 --> 00:08:27,000
and point at the content extracted from markdown.

160
00:08:27,000 --> 00:08:30,000
And of course, here we can use the shortcut.

161
00:08:30,000 --> 00:08:32,000
So that's now a object containing the data

162
00:08:32,000 --> 00:08:36,000
for a single post read from that markdown file.

163
00:08:36,000 --> 00:08:40,000
And that's what I wanna return here in getPostData.

164
00:08:41,000 --> 00:08:45,000
Okay, so now we have that getPostData function,

165
00:08:45,000 --> 00:08:48,000
we have getAllPosts where we get all those files.

166
00:08:48,000 --> 00:08:51,000
Now we wanna call, getPostData

167
00:08:51,000 --> 00:08:54,000
for every post we got here in getAllPosts.

168
00:08:56,000 --> 00:08:59,000
So there, we can of course, just create a for loop

169
00:09:00,000 --> 00:09:04,000
to go through all the postFiles we have here,

170
00:09:05,000 --> 00:09:09,000
like this for example, and for every file we wanna call,

171
00:09:09,000 --> 00:09:12,000
getPostData and pass the postFile,

172
00:09:12,000 --> 00:09:15,000
so the file name in the end to getPostData.

173
00:09:16,000 --> 00:09:19,000
And since in there we use readFileSync,

174
00:09:20,000 --> 00:09:23,000
we will block the fervor loop execution,

175
00:09:23,000 --> 00:09:26,000
until we parse the data, data.

176
00:09:26,000 --> 00:09:28,000
And that will be super fast, no worries.

177
00:09:28,000 --> 00:09:30,000
So that will not take long.

178
00:09:30,000 --> 00:09:31,000
It will be milliseconds.

179
00:09:32,000 --> 00:09:37,000
So then here we get our postData like this for a given post.

180
00:09:40,000 --> 00:09:43,000
And overall, we now wanna create an array

181
00:09:43,000 --> 00:09:46,000
of postData pieces.

182
00:09:46,000 --> 00:09:48,000
So an array off such post objects.

183
00:09:49,000 --> 00:09:51,000
And therefore, we can actually also change,

184
00:09:51,000 --> 00:09:52,000
this a little bit.

185
00:09:52,000 --> 00:09:56,000
In the end, what we wanna do is we wanna map our array

186
00:09:56,000 --> 00:10:01,000
of postFiles into an array of postData objects.

187
00:10:02,000 --> 00:10:05,000
So we could also just use postFiles and call map

188
00:10:07,000 --> 00:10:10,000
to execute some logic on every post file.

189
00:10:10,000 --> 00:10:12,000
And in the end, just return getPostData

190
00:10:13,000 --> 00:10:15,000
for the given post file.

191
00:10:15,000 --> 00:10:19,000
So then we would map our array of file names into an array

192
00:10:19,000 --> 00:10:24,000
of objects with the actual data for those different posts.

193
00:10:24,000 --> 00:10:27,000
And I think that makes more sense.

194
00:10:27,000 --> 00:10:29,000
Now, map returns a new array

195
00:10:29,000 --> 00:10:31,000
it does not change the existing array.

196
00:10:31,000 --> 00:10:34,000
So I will create a new allPosts array

197
00:10:34,000 --> 00:10:37,000
which is an array full of postData.

198
00:10:38,000 --> 00:10:41,000
Now maybe we also wanna sort that

199
00:10:41,000 --> 00:10:44,000
so that we have the latest posts first

200
00:10:44,000 --> 00:10:49,000
and hence I'll call allPosts sort here to sort my posts.

201
00:10:49,000 --> 00:10:52,000
It'll add my own sorting function here

202
00:10:52,000 --> 00:10:56,000
where we get postA and postB.

203
00:10:57,000 --> 00:10:59,000
And in the end, we wanna now check

204
00:10:59,000 --> 00:11:04,000
if postA.date is greater than postB.date.

205
00:11:05,000 --> 00:11:07,000
And if that's the case, return minus one,

206
00:11:07,000 --> 00:11:09,000
otherwise return one.

207
00:11:09,000 --> 00:11:12,000
That's the default JavaScript sort method

208
00:11:12,000 --> 00:11:16,000
which will make sure that posts with a greater date,

209
00:11:16,000 --> 00:11:21,000
so more recent posts are actually sort at,

210
00:11:22,000 --> 00:11:24,000
in front of older posts.

211
00:11:24,000 --> 00:11:29,000
That all returns a new array, the sortedPosts array

212
00:11:29,000 --> 00:11:31,000
and that's now what I'll return here,

213
00:11:31,000 --> 00:11:34,000
inside off this getAllPosts function.

214
00:11:35,000 --> 00:11:37,000
Now that was a lot of work,

215
00:11:37,000 --> 00:11:40,000
but I hopefully could make it clear what happens.

216
00:11:40,000 --> 00:11:43,000
But with that, we have the getAllPosts function

217
00:11:43,000 --> 00:11:47,000
which reads all the posts in the posts folder, no matter

218
00:11:47,000 --> 00:11:50,000
if that's one or multiple posts and then gets all the data

219
00:11:50,000 --> 00:11:54,000
for those posts and also sorts them and then returns them.

220
00:11:56,000 --> 00:11:58,000
Now to finish up the work on this file,

221
00:11:58,000 --> 00:12:01,000
I now just wanna add one other function

222
00:12:01,000 --> 00:12:05,000
which is responsible for getting all the featured posts.

223
00:12:05,000 --> 00:12:07,000
So I'll name it getFeaturedPosts.

224
00:12:08,000 --> 00:12:11,000
And here, I'll first of all get all posts again

225
00:12:11,000 --> 00:12:14,000
by calling getAllPosts.

226
00:12:14,000 --> 00:12:15,000
So that's simple.

227
00:12:17,000 --> 00:12:22,000
And then I'll just find out what my featured posts are

228
00:12:22,000 --> 00:12:25,000
by taking all posts and filtering them

229
00:12:25,000 --> 00:12:27,000
by calling filter on them.

230
00:12:27,000 --> 00:12:28,000
So here I'll then look

231
00:12:28,000 --> 00:12:32,000
at every single post and simply check if post isFeatured

232
00:12:32,000 --> 00:12:33,000
if that's true.

233
00:12:33,000 --> 00:12:35,000
If it's true, we'll keep it.

234
00:12:35,000 --> 00:12:37,000
If it's false, we'll drop it.

235
00:12:37,000 --> 00:12:40,000
So featuredPosts then only contains the posts

236
00:12:40,000 --> 00:12:42,000
where isFeatured is set to true.

237
00:12:42,000 --> 00:12:44,000
And then I'll return this here.

238
00:12:45,000 --> 00:12:49,000
That means that we still go through all posts first,

239
00:12:49,000 --> 00:12:51,000
but we'll have to do it anyways.

240
00:12:51,000 --> 00:12:53,000
We'll have to look into every file anyways

241
00:12:53,000 --> 00:12:56,000
to find out whether it's featured or not.

242
00:12:57,000 --> 00:12:59,000
If you don't wanna do that,

243
00:12:59,000 --> 00:13:02,000
you would have to keep an extra data source around,

244
00:13:02,000 --> 00:13:04,000
something like a json file

245
00:13:04,000 --> 00:13:07,000
which holds the slugs of all the featuredPosts.

246
00:13:07,000 --> 00:13:08,000
And then you would just read those

247
00:13:08,000 --> 00:13:12,000
and then just pull the specific markdown files

248
00:13:12,000 --> 00:13:15,000
which this extra json file points at.

249
00:13:15,000 --> 00:13:16,000
That could be an alternative

250
00:13:16,000 --> 00:13:19,000
for a bigger blog with hundreds or thousands

251
00:13:19,000 --> 00:13:23,000
of posts to increase the build performance a little bit,

252
00:13:23,000 --> 00:13:26,000
but for this block, this approach is absolutely fine.

253
00:13:27,000 --> 00:13:29,000
So now we've got all of this and now

254
00:13:29,000 --> 00:13:32,000
as a last step I'll export the getFeaturedPosts

255
00:13:32,000 --> 00:13:35,000
and the getAllPosts functions,

256
00:13:35,000 --> 00:13:38,000
because we will need those to fetch that data.

