Less than 100 lines of code, using Node to write a static blog generator

Now there are many popular static blog generation tools, such as hexo, hugo, etc. in fact, it is a simple process to manually implement a static blog generation tool. This article will take you to use node to implement a simple static blog generation tool. Our goal is to generate a static site from the markdown file. It only takes 5 steps, less than 100 lines of code.

1. Establish project

Create a new project directory first

mkdir node-site-generator && cd node-site-generator

Initialize project

npm init -y

Install some dependency packages. The specific functions of these dependency packages will be explained later

npm i del markdown-it parse-md walkdir --save

Then create a new main.js in the project directory. Because there is less code, all our code will be written here.

2. Collect markdown files

Create a new src directory in the root directory of the project, which is used to store all our markdown source files. First, we collect the paths of all markdown files in the directory, write a walk function, and use walkdir to traverse the src directory.

const walkdir = require('walkdir');

async function walk (srcPath){
    let result = await walkdir.async(srcPath,{return_object:true});
    const mdPaths = [];
    Object.entries(result).forEach(([path, fileStatus]) => {
        // walkdir will traverse all directories and files. I only collect the md file path in the traversal result
        if(!fileStatus.isDirectory() && path.match(/\.md$/ig)){
            mdPaths.push(path);
        }
    });
    return mdPaths;
}

3. Render markdown file to html

Create a new public folder in the root directory, and then a new articles directory in the public directory to store the generated static HTML files.

Follow the previous step to collect the file path to read the markdown file and generate the HTML static file.

Here we use the parse MD package and the markdown it package. Their functions are as follows:

  • Parse MD is used to read the meta information of makrdown, such as title, creation time, etc. the meta information is similar to the following format

    ---
    title: SQL Learning notes
    date: 2018-06-11
    ---
  • Markdown it is used to render markdown files into HTML

Continue to write the following in mian.js

const fs = require('fs'); // node native file module
const { default: parseMD } = require('parse-md');
const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();

// The htmlTemplate function fills the generated content string into the HTML template for reuse
function htmlTemplate(content, title = 'Site title', isArticle = false){
    return `<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Site title</title>
    <link rel="stylesheet" href="${isArticle ? '../styles.css' : './styles.css'}"> 
</head>
<body>
<header>${title}</header>
<ul>
    ${content}
</ul>
<footer> Simple Blog 2019-2020 </footer>
</body>
</html>
`;}

// Render markdown file as HTML static file
function parseMDtoHTML(paths = []){
    // Paths is an array that holds all the md file paths we collected in the previous step
    let indexData = [];
    for (let i = 0; i < paths.length; i++) {
        const str = fs.readFileSync(paths[i], 'utf8');
        // Read the source information and content of the markdown file, get the title, date, etc., and then use these meta information to generate the homepage
        const { metadata, content } = parseMD(str);
        const { title, date } = metadata;
        // indexData is used to generate the first page
        const mdHtml = md.render(content);
        const articleHtml = `<article>
                <h2>${title}</h2>
                <p>${date.toLocaleDateString()}</p>
                ${mdHtml}
            </article>`;
        const fileTitle = title.replace('/\s/g', '-');
        const writePath = `./public/articles/${fileTitle}.html`;
        fs.writeFileSync(writePath, htmlTemplate(articleHtml, 'Article page', true));
        indexData.push({ ...metadata, fileTitle });
    }
    return indexData;
}

4. Generate home page

It's not enough to generate HTML from markdown. We need a home page. In this step, we will generate a home page index.html for the static blog and generate it in the public directory. The home page should contain links to all article areas:

function generateIndex(indexData = []){
    // indexData uses an array of article meta information collected in part 3 to generate links to articles
    const listHTML = indexData.map(i => {
        return `
<li>
    <a href="./articles/${i.fileTitle}.html">${i.title}</a>
    <time>${i.date.toLocaleDateString()}</time>
</li>
`
    }).join('');

    // See Step 3 for details of htmlTemplate function
    const indexHTML = htmlTemplate(listHTML);
    fs.writeFile('./public/index.html', indexHTML, function () {
        console.log(`Write in index.html Success`);
    });
}

5. Write the entry function

Next, we write a start function at the bottom of main.js to concatenate the above procedures:

const del = require('del');

async function start() {
    // 1. del is used to delete the last generated static file
    del(['./public/articles/**.html', './public/index.html']);
    
    // 2. Collect the path of all markdown files in src directory
    const paths = await walk('./src');
    
    // 3. Read all markdown files and generate html
    const indexData = await parseMDtoHTML(paths);
    
    // 4. Generate homepage index.html
    await generateIndex(indexData);
}

// Execute start function
start();

Finally, execute node main.js startup in the project directory, and you can see the results generated in the public directory. In addition, in order to avoid the generated HTML static files being too simple, it is recommended to add a little style in the process of generating static HTML.

So far, a very simple static blog generator has been implemented, and many of the processes have been simplified. The main purpose is to elaborate the idea of generating static blog. If you want to complete a static blog generator with rich functions, there are still many areas to be improved.

Source code address: https://github.com/JohnSnow93/node-site-generator

Tags: node.js less npm SQL github

Posted on Tue, 05 Nov 2019 07:58:43 -0800 by jtravis