Linking Blog Content and Markdown conversion in Next.js
Tags: nextjs, javascript, beginners
Published: 2021-06-07 05:54:48

So far:
- We have set up a page to list blogs.
- Link blogs to their respective links

However, if we click on the individual blog, it is not showing relevant content. In this article, we fix this issue. And our blog URL presents relevant data to the users.

When this series started, I downloaded the content (in Markdown) from dev.to in JSON file saved in a data folder.  Now, we need to read the JSON file and load it in our blog.

Create the "Utilities" folder under the root of the application folder, and add the FileRead.js file under Utilities.

```javascript
import fs from 'fs';
import path from "path";


// Get All Blogs Details
export default function getAllBlogsData(fileName) {
    let blog = new Array()
    const data = getFileData(fileName)
    
    for (let index in data) {
        const catList = data[index].cached_tag_list
      
        blog.push({
            title: data[index].title,
            date: data[index].published_at,
            body: data[index].body_markdown,
            description: data[index].description,
            categories: catList,
            slug: data[index].slug
        });
    }

    // Reverse an Array
    const reverseData = blog.slice(0).reverse()

    return reverseData
}

// Get Individual Blog Data from slug
export function getBlogData(fileName, slug) {
    const data = getFileData(fileName)

    for (let index in data) {
        if (data[index].slug === slug) {
            return data[index]
        }
    }
    return 0
}

function getFileData(fileName) {
    const fileToRead = path.join(process.cwd(), fileName)
    return ( JSON.parse(fs.readFileSync(fileToRead)) )
}
```

We created a JavaScript file and, add the following functions:
- getAllBlogsData() - [To read all the data from the JSON file]
- getBlogData() - [To read the data for the individual blog]
- getFileData() - [Get all the data from the file in the JSON format]

In the index.js, first, import the getAllBlogsData function from the FileRead.js.

```javascript
import getAllBlogsData from "../Utilities/FileRead";
```

And then modify the getStaticProps(context) subroutine.

```javascript
export async function getStaticProps(context) {
    const data = getAllBlogsData('/data/articles.json')

    return  {
        props: {
            sample_blogs: data
        }
    }
}
```

Hmm, now our index.js file is cleaner :).

Open the file [slug].js and update the file with the following code:

```javascript
import BlogDetailsComponent from "../../components/Blog/BlogDetailsComponent";
import {getBlogData} from "../../Utilities/FileRead";
import CategoriesComponent from "../../components/Categories/CategoriesComponent";
import BlogComponent from "../../components/Blog/BlogComponent";

function IndividualBlogPage(props) {

    return (
        <div className="flex flex-auto">
            <CategoriesComponent />
            <BlogDetailsComponent blog={props}/>
            <div></div>
        </div>
    )
}

export async function getServerSideProps(context) {
    const fileName = '/data/articles.json';
    const { params } = context

    const blogData = getBlogData(fileName, params.slug)

    return {
        props:{
            title: blogData.title,
            date: blogData.published_at,
            body: blogData.body_markdown,
            description: blogData.description,
            categories: blogData.cached_tag_list,
            slug: params.slug
        }
    }
}

export default IndividualBlogPage
```
Up to this point, we pass the slug to the component and, we'll get the result for the individual blog post. 

Before proceeding, we also need to some styles to our blog.

Create a new file BlogStyles.js under the blog folder with the following code:

```javascript
import CSS from 'styled-jsx/css'

export default css.global `
    .blogs ul > li > ul > li {
      font-weight: 400;
      font-size: 0.8em;
    }

    p, ul, li {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif, Arial;
      letter-spacing: calc(0px * 16);
      line-height: calc(2.5px * 16);
      color: rgb(14, 16, 26);
      -webkit-font-smoothing: antialiased;
      animation-iteration-count: 1!important;
    }

    .blogs h1, p, ul {
      margin-left: 1.5em;
    }

    .blogs p { 
      display: block;
      font-size: calc(1.375px * 16);
      margin-block-start: 1em;
      margin-block-end: 1em;
      margin-inline-start: 1.5em;
      margin-inline-end: 1.5em;
      font-weight: 400;
    }

    .blogs ul {
      margin-left: 1.5em;
      font-size: 1.2em;
      list-style-type: disc;
    }

    .blogs ul > li {
      margin-left: 1.5em;
      font-weight: 400;
    }


    @media (min-width: 768px) {
      .blogs h1 {
        font-size: 1.5em;
        text-align: left;
        margin: 1.5em;
        font-weight: bold;
      }

      .blogs h2 {
        font-size: 1.2em;
        text-align: left;
        margin: 1.5em;
        font-weight: bold;
      }
    }
`
```

Now, we need to pass the javascript object to the BlogDetailsComponent.js file.

```javascript
import ReactMarkdown from 'react-markdown';
import styles from './BlogStyles'

function BlogDetailsComponent(props) {

    return (
        <div className={`ml-10 mt-4 w-3/5 container mr-4 shadow rounded border blogs `}>
            <ReactMarkdown >{props.blog.body}</ReactMarkdown>
            <style jsx global>
                {styles}
            </style>
        </div>
    )
} 

export default BlogDetailsComponent
```

If the 'react-markdown' package doesn't exist, please install it using the npm. 

We also have some code written for the tutorials but it is not showing correctly as of now. 

Please install 

```bash
npm install react-syntax-highlighter
```

And open the BlogDetailsComponent.js and add the following lines at the top of the file:

```javascript
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
```

And modify the function:

```javascript
function BlogDetailsComponent(props) {
    // let body = props.blog.body
    // let res = body.match(/<img.* \/>/g);
    // console.log(res)
    const customComponents = {

        code(code) {
            const { className, children } =  code

            let language = new Array();

            if (className) {
                language = className.split("-");
            }

            return (
                <SyntaxHighlighter language={language[language.length -1]} children={children} style={atomDark}   />
            )
        }
    }

    return (
        <div className={`ml-10 mt-4 w-3/5 container mr-4 shadow rounded border blogs `}>
            <ReactMarkdown components={customComponents}>{props.blog.body}</ReactMarkdown>
            <style jsx global>
                {styles}
            </style>
        </div>
    )
} 

export default BlogDetailsComponent
```

Refresh the page and, you'll see the highlighted syntax in our code blocks.

That's all for now. In the upcoming article, we fix the broken images.