设为首页 收藏本站
查看: 661|回复: 0

[经验分享] [原创]使用 NodeJS, MarkdownJS, PrettifyJS 打造个人博客写作平台

[复制链接]

尚未签到

发表于 2017-2-22 11:51:32 | 显示全部楼层 |阅读模式
引言
  上一篇文章我们介绍了使用 NodeJS, MarkdownJS, PrettifyJS 打造个人博客写作平台的整体思路, 也顺利解决了把 PrettifyJS 转换为 NodeJS 模块的麻烦。这篇文章我们会分析 NodeJS 相关代码,并给出可运行的压缩包下载。
  在继续本文之前,先来回答上篇评论中网友的疑问,这么做的好处有哪些? 如果我们有 Showdown 这样的在线转换 Markdown 语法的工具,这篇文章的意义在哪里?


  • 首先我希望使用记事本写文章,这样方便快捷。然后本机能够直接生成 HTML,这样我既可以直接放在我的个人主页,也可以粘贴到博客中。
  • 其次技术文章中,需要粘贴很多源代码,有 CSS, HTML, JavaScript 或者 Asp.NET, C# 的源代码,我希望这些源代码能自动着色,这样文章看起来更生动。 由于 Markdown 语法不支持为 <pre> 标签设置 class 属性,所以只能使用 Google 的 PrettifyJS,但是一般博客提供商是不会让你引入外部 JavaScript 的, 但大部分可以修改 CSS,这就需要在转换过程中直接生成着色后的 HTML,而这是 Showdown 不可能支持的。

实现
  首先来看看发布的压缩包的目录结构:

root
        lib
                nodejs
                        node.exe
                markdown
                        markdown.js
                        prettify-nodejs.js
                        build.js (所以的代码都在这里)
                        template.html (使用 prettify 在浏览器解析的页面模板)
                        template-prettify-inline.html (不包含 prettify JavaScript 文件的页面模板)
        nodejs_markdownjs
                intro.md (我们写的文章)
                build.bat (执行这个文件会把当前目录下的所有 .md 文件转化为 .html 文件)
  我们来看下 build.js 的内容:

var fs = require('fs'),
        markdown = require("./markdown"),
        path = require('path'),
        prettify = require('./prettify-nodejs');

// 可以传递第三个参数,如果为true则使用prettify的内联方式,不用加载JS
// 比如:..\lib\nodejs\node ../lib/markdown/build.js true
var prettifyInline = false;
if(process.argv.length >= 3) {
        prettifyInline = process.argv[2] === 'true' ? true : false;
}      
// 当前目录下的所有文件
var files = fs.readdirSync('./'),
        i = 0, count = files.length,
        file, dotLastIndex, fileName, fileType;
// 对所有以 .md 为后缀的文件,进行转换
for(; i < count; i++) {
        file = files;
        dotLastIndex = file.lastIndexOf('.');
        if(dotLastIndex >= 0) {
                fileType = file.substr(dotLastIndex + 1);
                if(fileType === 'md') {
                        fileName = file.substr(0, dotLastIndex);
                        buildFile(file, fileName);
                }
        }
}
// 获取模板文件内容
function getTemplate() {
        var markdownPath = path.dirname(process.argv[1]);
        if(prettifyInline) {
                markdownPath = markdownPath + '/template-prettify-inline.html';
        } else {
                markdownPath = markdownPath + '/template.html';
        }
        return fs.readFileSync(markdownPath, 'utf8');
}
// 转换 markdown 文件为html文件
function buildFile(file, fileName){
        console.log('Build file: ' + file);
        var fileContent, h1Regex, title = '';
        fileContent = fs.readFileSync(file, 'utf8');
        fileContent = markdown.toHTML(fileContent);
        // 从 html 中提取 h1 标签内的内容,作为网页的标题
        h1Regex = /<h1>([\w\W]*?)<\/h1>/.exec(fileContent);
        if(h1Regex && h1Regex.length === 2) {
                title = h1Regex[1];
        }
        // 转化为 prettify 需要的格式
        fileContent = fileContent.replace(/<pre><code>([\w\W]*?)<\/code><\/pre>/g, function(str, p1) {
                if(prettifyInline) {
                        // prettify 对单引号的处理有问题,这是权宜之策
                        p1 = p1.replace(/&#39;/g, "'");
                        // 如果是内联的 prettify,需要预先生成代码的 html 格式
                        p1 = prettify.prettyPrintOne(p1);
                }
                return '<pre class="prettyprint">' + p1 + '</pre>';
        });
        // 替换模板内容
        fileContent = getTemplate().replace('${title}', title).replace('${body}', fileContent);
        fs.writeFileSync(fileName + '.html', fileContent);
}
console.log('Done!');
  如果你用过 nodejs,上面的代码很好理解了,大致分为如下几个步骤:


  • 读取 build.bat 同级目录下的所有以 .md 为后缀的文件。
  • 对每个 .md 文件,调用 MarkdownJS 模块,转化为 HTML 源代码。
  • 提取 HTML 源代码中的 <h1> 标签作为页面的标题;对所有的 <pre><code>...</code></pre> 调用 PrettifyJS 模块,直接生成着色后的 HTML 代码。
  • 保存生成的 HTML 文件。

使用方法
  下载 Markdown 写作平台,解压缩到任意文件夹,然后和 lib 同级目录创建一个文件夹 HelloWorld,里面新建两个文件:
  build.bat

..\lib\nodejs\node ../lib/markdown/build.js true
  intro.md

## 段落一
下面是出自 [MDC Developer Center][1] 的一段 JavaScript 代码:

        s_obj = new String(s_prim = s_also_prim = "foo");
        s_obj.length;       // 3
        s_prim.length;      // 3
        s_also_prim.length; // 3
        'foo'.length;       // 3
        "foo".length;       // 3

[1]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String
  运行 build.bat,会在当前目录下生成 intro.html 文件,打开:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <style>
        .markdown-post h1
        {
                font-weight: bold;
                font-size: 2.2em;
                margin: 25px 0px 15px;
        }
        .markdown-post h2
        {
                font-size: 2em;
                font-weight: bold;
                margin: 25px 0 15px;
        }
        .markdown-post h3
        {
                font-weight: bold;
                font-size: 1.2em;
                margin: 10px 0px 5px;
        }
        ...
        </style>
</head>
<body>
<div class="markdown-post">
<h2>段落一</h2>
<p>下面是出自 <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String">MDC Developer Center</a> 的一段 JavaScript 代码:</p>
<pre class="prettyprint">
        <span class="pln">s_obj </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span>
        ...
</pre>
</div>
</body>
</html>
  需要注意的是:这个生成的 HTML 文件不包含任何 JavaScript 文件,但是代码都已经被着色了,实际的效果如下:


如何把生成的 HTML 添加为博客园随笔
  首先我们需要在博客园的后台管理中,进入“设置”标签,添加自定义的 CSS(这个 CSS 也就是生成的 intro.html 头部的CSS):

  在添加随笔时,打开 HTML 视图,把生成 HTML 的 <body> 部分的全部内容拷贝进去就可以了:

  如果你想看具体的示例,这篇文章和上篇文章就是最好的范例了。

下载可运行包
  下载可运行包

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345726-1-1.html 上篇帖子: nodejs之日志管理 下篇帖子: 大熊君大话NodeJS之------(Url,QueryString,Path)模块
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表