如今有不少流行的靜態博客生成工具,好比hexo
、hugo
等,其實手動實現一個靜態博客生成工具也是一個簡單的過程,本文就帶你們使用node實現一個簡單的靜態博客生成工具。咱們的目標是將markdown文件生成一個靜態的站點。只需5步,不到100行代碼量。javascript
先新建一個項目目錄css
mkdir node-site-generator && cd node-site-generator
初始化項目html
npm init -y
安裝一些依賴包, 這些依賴包具體做用後面會解釋到java
npm i del markdown-it parse-md walkdir --save
而後在項目目錄下新建一個main.js
,由於代碼比較少,咱們的全部代碼就寫到這裏。node
在項目根目錄下新建src
目錄,該目錄用於存放咱們全部的markdown源文件,咱們首先將該目錄下的全部markdown文件的路徑收集起來,編寫一個walk
函數,並使用walkdir
對src
目錄進行遍歷。git
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會遍歷全部目錄和文件,我只將遍歷結果中的md文件路徑收集起來 if(!fileStatus.isDirectory() && path.match(/\.md$/ig)){ mdPaths.push(path); } }); return mdPaths; }
在根目錄下新建public
文件夾,再在public
目錄下新建articles
目錄,用於存放生成好的靜態HTML文件。github
按照上一步收集到文件路徑讀取markdown文件,並將其生成HTML靜態文件。npm
這裏咱們用到了parse-md
包和markdown-it
兩個包,做用以下:數組
parse-md
用於讀取makrdown的元信息,如標題、建立時間等,元信息相似下面的格式markdown
--- title: SQL學習筆記 date: 2018-06-11 ---
markdown-it
用於將markdown文件渲染成HTML繼續在mian.js
編寫以下內容
const fs = require('fs'); // node原生的文件模塊 const { default: parseMD } = require('parse-md'); const MarkdownIt = require('markdown-it'); const md = new MarkdownIt(); // htmlTemplate函數將生內容字符串填充到HTML模板中,方便複用 function htmlTemplate(content, title = '站點標題', isArticle = false){ return `<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <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> `;} // 將markdown文件渲染爲HTML靜態文件 function parseMDtoHTML(paths = []){ // paths是一個數組,存放了咱們上一步中收集到全部的md文件路徑 let indexData = []; for (let i = 0; i < paths.length; i++) { const str = fs.readFileSync(paths[i], 'utf8'); // 讀取markdown文件的源信息和內容,獲得標題、日期等,以後生成首頁也要用到這些元信息 const { metadata, content } = parseMD(str); const { title, date } = metadata; // indexData以後用於生成首頁 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, '文章頁', true)); indexData.push({ ...metadata, fileTitle }); } return indexData; }
只將markdown生成HTML仍是不夠的,咱們還須要一個首頁,這一步咱們就給靜態博客生成一個首頁index.html
,並將其生成在public
目錄下,首頁要包含導航到全部文章區域的連接:
function generateIndex(indexData = []){ // indexData所用的是第三部中收集的文章元信息數組,用於生成文章的連接 const listHTML = indexData.map(i => { return ` <li> <a href="./articles/${i.fileTitle}.html">${i.title}</a> <time>${i.date.toLocaleDateString()}</time> </li> ` }).join(''); // htmlTemplate函數具體見第三步 const indexHTML = htmlTemplate(listHTML); fs.writeFile('./public/index.html', indexHTML, function () { console.log(`寫入index.html 成功`); }); }
接下來咱們在main.js
的最底部編寫一個start
函數,將上面的過程串聯起來:
const del = require('del'); async function start() { // 1. del用於刪除上一次生成的靜態文件 del(['./public/articles/**.html', './public/index.html']); // 2. 收集src目錄下的全部markdown文件的路徑 const paths = await walk('./src'); // 3. 讀取全部markdown文件並生成html const indexData = await parseMDtoHTML(paths); // 4. 生成首頁index.html await generateIndex(indexData); } // 執行start函數 start();
最後在項目目錄下執行node main.js
啓動,就能夠看到public
目錄下生成的結果。額外地,爲了不生成的html靜態文件太過樸素,建議在生成靜態HTML的過程當中加一點樣式。
到此就實現了一個很是簡單的靜態博客生成器,其中不少過程都簡化處理了,主要是爲了闡述生成靜態博客的思路,若是要完成一個功能豐富的靜態博客生成工具,還有不少能夠完善的地方。