Open brycewray opened 4 years ago
Would greatly appreciate an answer to my question, and I will understand if it's considered a "dumb noob" question. 😄
Would greatly appreciate an answer to my question, and I will understand if it's considered a "dumb noob" question. 😄
A friend of mine got through with this. I created a nested folder structure using the beta version.
The structure was like this Public -> Content -> Projects -> FolderA, FolderB, FolderA -> Project_1, Project_2, Project_1 -> landing image, cover_image, Project_1.md
The mock-config I used:
I used the hidden widget to hardcode that all projects in this particular setup are listed in Folder_A becuase for my particular project I needed to filter. And this Setup I repeated for Folder_B, etc. I could have made it more dynamic by adding a dropdown with the options Folder_A, Folder_B and setting that value in the path prop above, but if a user would miss-label, the post would end up somewhere else and they might have thought they deleted it.
I then needed a way to: -1 show all projects -2 access their data for path to the image etc. That's where my friend helped and came up with this code:
//folder lib/api.js
import fs from 'fs'
import { join } from 'path'
import matter from 'gray-matter'
const postsDirectory = join(process.cwd(), 'public', 'content', 'projects')
export function getPostSlugs() {
return walkSync(postsDirectory)
}
// List all files in a directory in Node.js recursively in a synchronous fashion
const walkSync = function(dir, filelist) {
var fs = fs || require('fs'),
files = fs.readdirSync(dir);
filelist = filelist || [];
files.forEach(function(file) {
if (fs.statSync(dir + '/' + file).isDirectory()) {
filelist = walkSync(dir + '/' + file, filelist);
}
else {
if(file.endsWith(".md")){
console.log(dir, file)
let post = {
directory: dir,
file: file
};
filelist.push(post);
}
}
});
return filelist;
};
export function getPostBySlug(slug, fields = []) {
const fullPath = slug.directory + '/' + slug.file;
const fileContents = fs.readFileSync(fullPath, 'utf8')
const { data, content } = matter(fileContents)
const items = {}
// Ensure only the minimal needed data is exposed
fields.forEach((field) => {
if (field === 'slug') {
items[field] = slug.file
}
if (field === 'content') {
items[field] = content
}
if (data[field]) {
items[field] = data[field]
}
})
return items
}
export function getAllPosts(fields = []) {
const slugs = getPostSlugs()
const posts = slugs
.map((slug) => getPostBySlug(slug, fields))
// sort posts by date in descending order
.sort((post1, post2) => (post1.date > post2.date ? '-1' : '1'))
return posts
}
IN PROJECTS PAGE
import React, { useEffect } from 'react'
import { getAllPosts } from '../lib/api'
const Projects = ({ allProjects }) => {
return (
<div>
<ProjectPage projects={allProjects}/>
</div>
)
}
export async function getStaticProps () {
// These are all the props from your markdown file
const allProjects = getAllPosts([
'title',
'date',
'slug',
'anotherProp',
])
return {
props: { allProjects },
}
}
export default Projects
Hope this helps happy new year! :)
Thanks very much, @ReangeloJ! Happy 2021 to you, too.
This repo and the accompanying article on the Netlify blog are very helpful!
What additional config, and in which file(s), would be required to let this properly handle routing for Markdown files in nested directories — so that, for example, the final path would be something like
example.com/post/dirlevel1/dirlevel2/dirlevel3/my-post
for a Markdown file in/posts/dirlevel1/dirlevel2/dirlevel3/
? It currently can detect such a file's presence but it's unclear what the correctpathname
reference should be in/components/PostList.js
to provide the right URL. Most Next.js-to-blog tutorials similarly seem to assume only one level of Markdown posts, but this becomes impractical after a while.Thanks for any consideration you can give to this request.