John Mann

John Mann

Previous and Next for Next js


So I wrote a node script to update my previous and next for every blog entry and then it would write it out in markdown as part of the header, so it would look like this:

---
title: "Practice does not make perfect"
date: "2018-04-15"
next: "simplicity-over-complex"
prev: "building-teams-and-careers"
---

And it would sort my posts by date, so it would automatically find the next one and previous appropriately. And also, it would need to not show previous if on the first and not show next if on the last, that was a little react variable code, super simple.

    const prevLink = postData.prev ? (<Link href="/posts/${postData.prev}" as={`/posts/${postData.prev}`}>
                        <a className="prevLink">Previous</a>
                    </Link>) : ''
    const nextLink = postData.next ? (<Link href="/posts/${postData.next}" as={`/posts/${postData.next}`}>
                        <a className="nextLink">Next</a>
                    </Link>) : ''

But it was fun creating something that will change the prev/next if the date is different. I'll write more about it in a bit, but wanted to get this down. I used the NextJS blog functions in node, and then parsed it using greymatter like they did.

Ok, I'll do it now.

var fs = require('fs')
var path = require('path')
var matter = require('gray-matter')

const postsDirectory = path.join(process.cwd(), 'source')
const outputDirectory = path.join(process.cwd(),'posts')

function getSortedPostsData() {
    // Get file names under /posts
    const fileNames = fs.readdirSync(postsDirectory)
    const allPostsData = fileNames.map(fileName => {
        // Remove ".md" from file name to get id
        const id = fileName.replace(/\.md$/, '')

        // Read markdown file as string
        const fullPath = path.join(postsDirectory, fileName)
        const fileContents = fs.readFileSync(fullPath, 'utf8')

        // Use gray-matter to parse the post metadata section
        const matterResult = matter(fileContents)
        const contentData = matterResult.content
        // Combine the data with the id
        return {
            id,
            contentData,
            ...matterResult.data
        }
    })
    // Sort posts by date
    return allPostsData.sort((a, b) => {
        if (a.date < b.date) {
            return 1
        } else {
            return -1
        }
    })
}

function writeNewData(data){
    data.map(item => {
        const outputFile = path.join(outputDirectory, item.id + '.md')
        nextIndex = item.index - 1
        prevIndex = item.index + 1
        output = ''
        if (item.index == 0){
            output = '---\n' +
                'title: "' + item.title + '"\n' +
                'date: "' + item.date + '"\n' +
                'prev: "' + data[prevIndex].id + '"\n' +
                '---';
        }else if (data[prevIndex] == undefined){
            output = '---\n' +
                'title: "' + item.title + '"\n' +
                'date: "' + item.date + '"\n' +
                'next: "' + data[nextIndex].id + '"\n' +
                '---';
        }else{
            output = '---\n' +
                'title: "' + item.title + '"\n' +
                'date: "' + item.date + '"\n' +
                'next: "' + data[nextIndex].id + '"\n' +
                'prev: "' + data[prevIndex].id + '"\n' +
                '---';
        }
        output += '\n' + item.contentData
        fs.writeFile(outputFile, output, { flag: 'w' }, function (err) {
            if (err) return console.log(err);
        });
    })
}


const data = getSortedPostsData()

// Adds an index for prev/next output
Object.values(data).forEach((data, index)=> {
        data.index = index
    }
);

writeNewData(data)

That's it. I read it, add it, and write it.

Battery dying on laptop. Night for now.

PreviousNext