Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested Markdown files? (Information request) #6

Open
brycewray opened this issue Jun 19, 2020 · 3 comments
Open

Nested Markdown files? (Information request) #6

brycewray opened this issue Jun 19, 2020 · 3 comments

Comments

@brycewray
Copy link

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 correct pathname 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.

@brycewray
Copy link
Author

Would greatly appreciate an answer to my question, and I will understand if it's considered a "dumb noob" question. 😄

@ReangeloJ
Copy link

ReangeloJ commented Jan 4, 2021

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:

  • label: "Projects for folder A"
    label_singular: 'Project folder A'
    name: "projects_FolderA"
    folder: "public/content/projects"
    create: true
    media_folder: ''
    public_folder: ''
    path: '{{folderName}}/{{title}}/{{slug}}'
    filter: {field: "folderName", value: "Folder_A"}
    fields:
    - {label: "Project Name" , name: "title", widget: string, description: "This is the name of the markdown file."}
    - {label: "project", name: "folderName", widget: "hidden", default: "Folder_A"}
    - {label: "anotherProp" , name: "anotherProp", widget: string,"}

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! :)

@brycewray
Copy link
Author

Thanks very much, @ReangeloJ! Happy 2021 to you, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants