Markdown转HTML之Node篇

简介: 前言环境及编码搭建环境expressmarkdown-itcommanderrd核心编码cmd_preview模块cmd_build模块打造命令行工具写点xxmd演示总结前言之前用Python写过类似的工具,更能上来说一般般。

前言

之前用Python写过类似的工具,更能上来说一般般。而且实用性不是很强。http://blog.csdn.net/marksinoberg/article/details/51863506

然后好巧不巧又看到了一个Node上的相关模块,看起来渲染效果比我那个好多了。联想到hexo这款静态博客生成工具,就思量着也大致的做一下。

环境及编码

接下来简单的模拟一下相关的实现。代码比较凌乱,思维比较混乱,还望海涵(虽然主要是作为我自己的笔记,但如果对你有些许帮助,那就不枉我码了这么多字咯)。

搭建环境

所依赖的第三方模块有如下几个:

  • express: 开启本地服务, 预览生成效果。
  • Markdown-it: 渲染md文件为HTML内容。
  • rd: 一个读取文件夹内容的好帮手。
  • commander: 制作命令行工具的一大利器。

下面简要对这几个模块进行阐述,以及相关的使用技巧。

express

express不仅作为对connect的高层封装,更包含了一些额外的处理。所以我们可以方便的进行路由控制,这对于本次的工具而言,是个不错的选择。

// 初始化服务器
    var app = express();
    var router = express.Router();
    app.use('/assets', server_static(path.resolve(dir, 'assets')));
    app.use(router);

    // 渲染文章
    router.get('/posts/*', function(req, res, next){
        var name = stripExtname(req.params[0]);
        // 渲染req.params[0]对应的文章,然后展示给前台
        res.end(html);
        });

        // res.end(req.params[0]);
    });

    // 渲染列表
    router.get('/', function(req, res, next){
        // 读取源文件目录, 渲染出列表内容。
        res.end('list of articles.');
    });

    app.listen(8080);

markdown-it

相对于Python中的那些第三方库,我倒是觉得Node中与其也没甚么两样。使用起来同样很简单。

第一步,引入依赖

let markdowner = require('markdown-it');

第二步, 配置构造器

var md = new markdowner({
    html: true,
    prefix: 'code-',
});

第三步, 调用渲染方法,获取渲染后内容

var html = md.render(sourcedata||'');

如此,便是markdown-it的基础内容了,待会将在代码中更加详细的运用。

commander

用过Python的argparser的估计都知道,很方便的一个处理命令行参数的第三方库。不过Node中的commander用起来更方便。

下面简单的介绍一下使用流程。详细内容还是看人家的官网吧,如下:
https://www.npmjs.com/package/commander

第一步, 安装模块

npm install commander --save

第二步,编码

/**
 * 一个命令行工具库。
 */

let commander = require('commander');

// help 命令
commander.command('help')
         .description('显示工具如何使用的帮助信息')
         .action(function(){
             commander.outputHelp();
         });

// create 命令
commander.command('create [dirname]')
         .description('创建一个空的博客')
         .action(function(dirname){
            console.log(dirname+' 创建完成。')
         });

// preview 命令
commander.command('preview [dirname]')
         .description('预览获取到的Markdown文件夹内容')
         .action(function(dirname){
            console.log(' preview of %s', dirname);
         });
        //  .action(require('./cmd_preview'));

// build 命令
commander.command('build [dirname]')
         .description('根据给定的文件夹路径生成HTML内容.')
         .option('-o OR --output <dirname>', '导出生成的HTML存放的路径')
         .action(function(dirname){
            console.log('build based on %s', dirname);
         });
        // .action(require('./cmd_build'));

// 解析相关命令
commander.parse(process.argv);

第三步, 查看效果
**commander**运行效果

如果想更加方便一点,直接使用命令来操作。使用

npm link

当然了,还需要设置一下对应的package.json文件内容。这里不过多叙述了。

rd

我这里的需求是读取_posts文件夹下的Markdown源文件,所以只需要readFile方法即可。
具体代码如下:

rd.readFile(sourcedir, function(err, files){
        if(err){
            console.log('读取文件夹内容失败!');
            return;
        }
        // 遍历文件夹列表,对每一个文件执行渲染操作。
        files.forEach(function(file){
            // 做自己的逻辑处理即可。
        });
    });

这个模块比较简单,有兴趣的可以参考下面的作者链接。
https://github.com/leizongmin/node-rd

核心编码

下面正式开始今天的主题,做一个带预览功能的Markdown文件转HTML页面的工具。

cmd_preview模块

/**
 * 关于预览实现相关的代码。
 */

let express = require('express');
let path = require('path');
let markdowner = require('markdown-it');
let fs = require('fs');
let rd = require('rd');

var md = new markdowner({
    html: true,
    langPrefix: 'code-',
});




module.exports = function(dir) {
    dir = dir || '.';

    // 初始化服务器
    var app = express();
    var router = express.Router();
    app.use(router);

    // 渲染文章
    router.get('/posts/*', function(req, res, next){
        var name = stripExtname(req.params[0]);
        var file = path.resolve(dir, '_posts', name+'.md');
        console.log('---dir--', dir);
        console.log('---name--', name);
        console.log('---file--', file);

        fs.readFile(file, function(err, content){
            if(err){
                console.log('读取文件失败!');
                res.end(JSON.stringify(err)+"\n");
                return next(err);
            }
            res.writeHead(200, {"Content-Type": "text/html;charset=UTF-8"});
            var html = markdownTOHTML(content.toString());
            console.log('读取文件成功, 解析后的内容为:\n', html);
            res.end(html);
        });

        // res.end(req.params[0]);
    });

    // 渲染列表
    router.get('/', function(req, res, next){
        var sourcefolder = path.resolve(dir, '_posts');
        rd.readFile(sourcefolder, function(err, files){
            if(err){
                console.log('读取文件夹内文件失败!');
                return next(err);
            }
            res.writeHead(200, {"Content-Type": "text/html;charset=UTF-8"});
            var html = "<html><h1>Markdown 转 HTML 实时预览</h1><hr><br />";
            files.forEach(function(filepath){
                html += "<a href='/posts/"+ get_file_name(filepath) +".md' target='_blank'>"+get_file_name(filepath)+"</a><br /><br />";
            });
            html += "</html>";
            res.end(html);
        }); 


        // res.end('list of articles.');
    });

    app.listen(8080);
};


function stripExtname(name) {
    var i = 0-path.extname(name).length;
    if(i==0) i=name.length;
    return name.slice(0, i);
}

function get_file_name(fullname){
    var ls = fullname.toString().split('\\');
    var filename =  ls[ls.length-1].split('.');
    // console.log('ls--', ls);
    // console.log('filename--', filename);
    return filename[0];
}

function markdownTOHTML(content) {
    return md.render(content||'');
}

cmd_build模块

/**
 * 实现Markdown文件到HTML文件的转换。
 */

let markdowner = require('markdown-it');
let rd = require('rd');
let path = require('path');
let fs = require('fs');

var md = new markdowner({
    html: true,
    langPrefix: 'code-',
})


module.exports = function(dir) {
    dir = dir || '.';
    console.log('当前文件路径为:', dir);

    // 读取出给定目录下的所有的文件
    // 将所有Markdown文件依次转成HTML页面,并进行保存操作。
    get_files_by_dir(dir);
}

function get_files_by_dir(dir) {
    // 计算出源文件的路径
    var sourcedir = path.resolve(dir, '_posts');
    var publicdir = path.resolve(dir, 'public');
    rd.readFile(sourcedir, function(err, files){
        if(err){
            console.log('读取文件夹内容失败!');
            return;
        }
        // 遍历文件夹列表,对每一个文件执行渲染操作。
        files.forEach(function(file){
            var html = md2html(file);
            var filename = get_filename_by_path(file);
            var output = path.resolve(publicdir, filename+'.html');
            console.log('保存路径为:', output);
            save_html_content(html, output);
            console.log('%s.html 生成成功!', filename);
        });
    });
}

function md2html(filepath){
    var content = fs.readFileSync(filepath);
    var html = md.render(content.toString()||'');
    return "<html><head><meta charset='UTF-8'><title>"+get_filename_by_path(filepath)+"</title></head>"+html+"</html>";
}

function save_html_content(content, outpath){
    fs.writeFile(outpath, content, function(err){
        if(err){
            console.log('save_html_content: 保存文件内容失败!');
            return;
        }
        console.log('save_html_content: %s 保存成功!', outpath);
    });
}

function get_filename_by_path(filepath){
    var paths = filepath.toString().split('\\');
    return paths[paths.length-1].split('.')[0];
}

打造命令行工具

还是用刚才的hello.js,现在稍微修改一下action里面的内容,对应我们刚才做的那两个小模块,做下修改即可。完整代码如下:

/**
 * 一个命令行工具库。
 */

let commander = require('commander');

// help 命令
commander.command('help')
         .description('显示工具如何使用的帮助信息')
         .action(function(){
             commander.outputHelp();
         });

// create 命令
commander.command('create [dirname]')
         .description('创建一个空的博客')
         .action(function(dirname){
            console.log(dirname+' 创建完成。')
         });

// preview 命令
commander.command('preview [dirname]')
         .description('预览获取到的Markdown文件夹内容')
        //  .action(function(dirname){
        //     console.log(' preview of %s', dirname);
        //  });
         .action(require('./cmd_preview'));

// build 命令
commander.command('build [dirname]')
         .description('根据给定的文件夹路径生成HTML内容.')
         .option('-o OR --output <dirname>', '导出生成的HTML存放的路径')
        //  .action(function(dirname){
        //     console.log('build based on %s', dirname);
        //  });
        .action(require('./cmd_build'));

// 解析相关命令
commander.parse(process.argv);

写点xx.md

巧妇难为无米之炊, 现在先在hello.js的同级目录下建个文件夹_posts,里面写点xx.md文件,然后建一个public文件夹保存生成的HTML文件。比如我的目录结构是这样的。

E:\Code\Nodejs\learn\libs-learn\commander-related>tree /f .
卷 文档 的文件夹 PATH 列表
卷序列号为 0000-4823
E:\CODE\NODEJS\LEARN\LIBS-LEARN\COMMANDER-RELATED
│  cmd_build.js
│  cmd_preview.js
│  hello.js
│
├─public
│
└─_posts
        helloworld.md
        second.md

演示

首先是预览实现,在命令行里输入以下命令:

node hello.js preview . # .代表当前目录

结果如下:
**preview**效果图


然后是针对每一篇文章生成效果的演示。

每一篇文章的预览效果


最后就是看下build功能的实现。

现在在命令行里面输入以下命令:

node hello.js build . # .代表当前目录

然后看下效果。
**build** 功能实现


总结

大致来说功能就算是完成了,但是目前这样子是没法直接应用的。很多东西都需要润色,比如:

  • 模板化HTML页面处理。
  • 命令行选项的link实现。
  • 通过监测文件内容变化实现实时预览

就先到这里吧,今天又发现了两个不错的网址,然后还是先去学一波,补充补充知识吧。很多时候,不是能力不够,而是见识不足

目录
相关文章
|
6月前
|
JavaScript 前端开发 编译器
Nodejs 第二十三章(Markdown 转 html)
Nodejs 第二十三章(Markdown 转 html)
102 0
|
机器学习/深度学习 存储 资源调度
如何将html转换成markdown?
如何将html转换成markdown?
225 0
|
5月前
|
存储 移动开发 编解码
基于HTML5开发的Markdown在线编辑器
Markdown是一种轻量级标记语言,以其简洁易读的格式而备受程序员和作者们的青睐。随着互联网的发展,越来越多的在线Markdown编辑器应运而生,为用户提供了更加便捷、高效的写作和编辑环境。本文将探讨基于HTML5开发的Markdown在线编辑器的设计原理、功能特点以及技术优势。
122 4
|
2月前
|
移动开发 前端开发 HTML5
Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)
本文介绍了Twaver HTML5中的拓扑元素(Element),包括网元(Element)、节点(Node)和连线(Link)的基本概念和使用方法。文章详细解释了Element的属性和方法,并通过示例代码展示了如何在React组件中创建节点、设置节点属性和样式。
44 1
Twaver-HTML5基础学习(8)拓扑元素(Element)_网元(Element)、节点(Node)
|
3月前
Markdown使用HTML语法实现复杂表格
Markdown使用HTML语法实现复杂表格
150 1
|
3月前
|
JavaScript 算法 前端开发
学习 node.js 六 Markdown 转为 html,zlib
【8月更文挑战第19天】
26 0
|
3月前
Html 表格 在线转 Markdown
Html 表格 在线转 Markdown
45 0
|
4月前
|
自然语言处理 开发者 Python
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的 HTML 内容。Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强。
Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的 HTML 内容。Markdown 的语法简洁明了、学习容易,而且功能比纯文本更强。
|
6月前
|
存储 移动开发 编解码
基于HTML5开发的Markdown在线编辑器
Markdown是一种轻量级标记语言,以其简洁易读的格式而备受程序员和作者们的青睐。随着互联网的发展,越来越多的在线Markdown编辑器应运而生,为用户提供了更加便捷、高效的写作和编辑环境。本文将探讨基于HTML5开发的Markdown在线编辑器的设计原理、功能特点以及技术优势。
79 1
基于HTML5开发的Markdown在线编辑器
|
4月前
|
Unix Linux Shell
Sphinx是一个Python文档生成工具,它可以解析reStructuredText或Markdown格式的源代码注释,并生成多种输出格式,如HTML、LaTeX、PDF、ePub等。
Sphinx是一个Python文档生成工具,它可以解析reStructuredText或Markdown格式的源代码注释,并生成多种输出格式,如HTML、LaTeX、PDF、ePub等。
下一篇
无影云桌面