基于node实现Markdown文件转换为HTML文件,并支持浏览器端的实时刷新

该案例的完整源代码地址为:

https://github.com/linqian123...

这个案例的整体功能描述为,利用node当中的fs模块实时监视指定的Markdown文件当中的内容变化,(该Markdown文件的路径以相对于当前js脚本文件的形式,作为命令行的参数传入),一旦其内容发生了修改,即使用fs模块读取该文件的内容,并利用第三方模块marked来将其Markdown代码转换为对应的html代码,之后再利用github-markdown-css给其加入样式,再完成骨架拼接,最后将完整的html代码写入同目录下的同文件名,后缀名为.html的文件当中,写入成功之后,再调用第三方模块包browser-sync来实现浏览器端的实时刷新。

1、实时监视Markdown文件的变化

一开始的文件的结构如下所示

基于node实现Markdown文件转换为HTML文件,并支持浏览器端的实时刷新

fs模块当中用于监视文件变化的方法fs.watchFile(filename[,options],listener(curr,prev));其中filename参数为被监听的文件的绝对物理路径。可选参数options为一个对象,默认为{persistent:true,interval:5007},即代表处于持续监听的状态,并且默认的时间间隔为5s左右。可以通过改变interval的值来使得间隔时间变短,减少延时。listener(curr,prev)为一个回调函数,当被监听的那个文件发生变化,并且在用户进行保存操作(即ctrl+s将内存当中编辑的文本写进磁盘)时,触发该回调函数。
使用process.argv[2]来获取命令行当中传入的参数(用法见 node.js当中的全局成员与path模块的使用)。用户在命令行当中输入该Markdown文件相对于当前js脚本文件的相对路径。用法如下所示:

基于node实现Markdown文件转换为HTML文件,并支持浏览器端的实时刷新

2、读取文件内容并转化为对应的HTML代码

在上述的listener(curr,prev)的回调函数当中先对currprev这两个文件状态对象的mtime进行比较,从修改时间上进行判断文件在ctrl+s保存之后其内容是否真的发生了变化,以此来减少不必要的转化。再确定文件内容真的发生改变之后,再开始读取文件的操作。

fs.watchFile(target,{persistent:true,interval:200},(curr,prev)=>{
    if(curr.mtime === prev.mtime){
        return false;
    };
    fs.readFile(target,'utf8',(err,data)=>{
        if(err) throw err;
        console.log(data);
    });
});

在读取了Markdown文件内容之后,再利用marked这个第三方的模块包,将Markdown中的代码直接转换为对应的html代码。
先用命令->npm install marked 来下载该模块包,再用const marked = require('marked');来引包。var html = marked(data);console.log(html);

基于node实现Markdown文件转换为HTML文件,并支持浏览器端的实时刷新

3、完成html代码的样式添加与骨架拼接

先给转化后的html代码加上Markdowncss样式,可以使用当前市面上最被认可的一套Markdown样式。在github上搜索github-markdown-css,完成下载之后,将解压文件夹当中的github-markdown.css文件放入当前的项目文件夹当中。我们可以在该文件夹的readme.md文件当中了解其用法。
官方的提示用法为

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="github-markdown.css">
<style>
    .markdown-body {
        box-sizing: border-box;
        min-width: 200px;
        max-width: 980px;
        margin: 0 auto;
        padding: 45px;
    }

    @media (max-width: 767px) {
        .markdown-body {
            padding: 15px;
        }
    }
</style>
<article class="markdown-body">
    <h1>Unicorns</h1>
    <p>All the things</p>
</article>

即我们需要在我们自己的代码当中复制这两个style样式代码,并将Markdown代码包裹在一个类名为"markdown-body"div当中。
接下去进行html代码的完整骨架的拼接。

var template = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .markdown-body {
                box-sizing: border-box;
                min-width: 200px;
                max-width: 980px;
                margin: 0 auto;
                padding: 45px;
            }
            @media (max-width: 767px) {
                .markdown-body {
                    padding: 15px;
                }
            }
            {{{style}}}
        </style>
    </head>
    <body>
        <div class="markdown-body">
            {{{content}}}
        </div>
    </body>
    </html>
`;

这里的字符串拼接使用ES6语法当中的模板字符串,之后用读文件的方式把github-markdown-css当中的内容读取出来之后,用replace方法将其替换template字符串当中的{{{style}}}部分,而{{{content}}}部分用Markdown文件内容来替换。

完成内容拼接之后,将完整的html代码写入同目录下的同文件名,后缀名为.html的文件当中。

4、使用browser-sync来实现浏览器端的自动刷新

4.1 通过命令->npm install brower-sync来下载这个第三方模块包。
4.2 再用const browserSync = require('browser-sync');来引包。
4.3 通过browserSync来启动创建一个文件服务器。
browserSync({
    browser: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
    server:path.dirname(target),
    index:path.basename(filename),
    notify:false
});

browser属性值为我们希望使用的浏览器,打开我们的文件,写入该浏览器应用程序在本机上的绝对物理路径。server属性值为该文件服务器的根目录,index属性值为访问该静态服务器时,打开的默认的索引文件。notify:false这个参数的设置可以关闭每次完成浏览器端的刷新时弹出的提示信息。

4.4 使用browserSync.reload(文件名)完成浏览器端的自动刷新

在写入操作完成的回调函数当中,使用该语句,完成浏览器端的自动刷新。

fs.writeFile(filename,allHtml,'utf8',(err)=>{
    if(err) throw err;
    console.log('写入成功!');
    browserSync.reload(path.basename(filename));
});

这样就完成了Markdown文件转换为HTML文件,并支持浏览器端的实时刷新。

相关推荐