本片为《用node.js建博客》系列的最后一篇,如果你第一看到这个系列, 可以在文章结尾看到前几篇。
技术准备
1. 如何添加代码高亮支持
代码美化选用Google-code 的 PrettyPrint。使用非常方便,能够自动匹配语言。
2. 使用CSS框架完成最基本的美化(本片将不涉及)
CSS框架打算用BluePrint, 如果只需要Grid, 选用960Grid也不错。
?
思路
以前采用的是直接渲染markdown的方式。在Express中注册一个markdown渲染器,在response时将markdown渲染输出。这种方式的缺点就是不好对输出的html进行修改(比如添加js,css等).?
因此需要修改markdown的渲染方式,将markdown嵌入到jade模板中。
?
Let's do it:
1. 修改测试:
test/page-test.js
?
var vows = require('vows'); var apiEasy = require('api-easy'); var assert = require('assert'); var jsdom = require('jsdom').jsdom; var suite = apiEasy.describe('blogs'); suite.discuss("when visit home page") .discuss('can view blog list and it should response 200 status') .use('localhost', 3000) .setHeader('Content-Type', 'text/html; charset=utf-8') .get() .expect(200) .expect("should respond with x-powered-by", function(err, res, body) { // express assert.include(res.headers, 'x-powered-by'); }) .expect("should respond with 'Nodeblog - Home' title", function (err, res, body) { var doc = jsdom(body); //匹配title assert.equal(doc.title, "NodeBlog - Home"); }) .export(module);
?
test/blogs-test.js
?
var vows = require('vows'); var apiEasy = require('api-easy'); var assert = require('assert'); var jsdom = require('jsdom').jsdom; var suit = apiEasy.describe("/blogs/*.html") suit.discuss('when vists the markdown blog,') .use('localhost', 3000) .setHeader('Content-Type', 'text/html; charset=utf-8') .path('/blogs/') .discuss('if the markdown file is exists, show blog') .get('monitor_doc') .expect(200) .expect("should respond 'NodeBlog - Blogs' title", function (err, res, body) { var doc = jsdom(body) assert.equal(doc.title, 'NodeBlog - Blogs'); }) .undiscuss() .discuss('if the markdown file is not exists') .get('unknow') .expect(404) .expect("should respond 'NodeBlog - 404' title", function (err, res, body) { var doc = jsdom(body) assert.equal(doc.title, 'NodeBlog - 404') }) .export(module);
2. 在views/blogs/下添加show.jade
该文件用于显示 markdown blog
?
views/blogs/show.jade:
div.blog_main !{blog_content}
?
? 此时需要用 !{} 不能使用 #{}, 否则jade会将"<",">"当特殊字符处理,将其转换成转移字符。
?
3. 修改app.js?
?
app.get('/blogs/:title', function(req, res, next) { var urlPath = [ // 获取相对路径, 我的应该是: // /Users/lvjian/projects/nodejs/nodeblog process.cwd(), '/views/blogs/', req.params.title, '.md' ].join(''); var filePath = path.normalize(urlPath) path.exists(filePath, function (exists) { if(!exists) { console.log('jump 404'); next(); } else { var content = fs.readFileSync(filePath, config.encoding); // 这里将markdown转成html, 然后以参数形式输出 var html_content = markdown.parse(content); res.render('blogs/show', { title: config.app + " - Blogs" , blog_content: html_content }); } }); })
?
此时启动app, 访问博客可看到效果.?
?
4. 为show.jade添加prettyprint支持:
下载prettyprint, 将其放到 ./public/lib/ 文件夹下:
?
?
在show.jade文件中使用:
?
link(rel='stylesheet', href='/libs/prettify/sunburst.css', type="text/css") script(type='text/javascript', src='/libs/prettify/prettify.js') script(type='text/javascript', src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js') style(type="text/css") h1 { text-align: center; } div.blog_main !{blog_content} script // markdown-js会用<code><pre></pre></code>将代码包起来 // 不过无法为其添加prettyprint class属性 // 这里采用jquery手动添加 $('code, pre').addClass('prettyprint'); prettyPrint();
?
看一下效果:
?
What' next? ?Final了还有next...???
为什么Final?
边写博客边coding有点太慢了,打算先将博客建好,之后以技术应用为主题写文章。
?
接下来要做什么:
- 采用mongodb保存markdown数据,node.js中mongoose模块提供了对mongodb的支持
- 添加用户认证(当然为了保证暂时只能我自己用)
- 设计REST-ful接口,并且创建node commandline工具,让我可以用Textmate/MacVim直接写博客。
?
其实, 可以仍然用引擎渲染md的办法, 而不用输出html的办法
只需要准备一个layout, express会自动将md转化好的结果输出到body上的
你可以试一下
res.render(path, {layout: 'layout_doc'});
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Doc</title> <link href="/google-code-prettify/prettify.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="/google-code-prettify/prettify.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('pre code').addClass('prettyprint'); prettyPrint(); }); </script> </head> <body> <div id="body"> <div id="content"> <%- body %> </div> </div> </body> </html>
另外, md转换以后的代码是什么意思呢? 去掉了html中的什么?
return html.replace(/\{([^}]+)\}/g, function(_, name){ console.log(name, locals[name]); return locals[name]; });
这样做的后果就是如果md文档里面有代码会输出错误的内容
直接 return html; 好了.