基于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文件的变化
一开始的文件的结构如下所示
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
脚本文件的相对路径。用法如下所示:
2、读取文件内容并转化为对应的HTML代码
在上述的listener(curr,prev)
的回调函数当中先对curr
和prev
这两个文件状态对象的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);
3、完成html代码的样式添加与骨架拼接
先给转化后的html
代码加上Markdown
的css
样式,可以使用当前市面上最被认可的一套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文件,并支持浏览器端的实时刷新。