-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.js
107 lines (98 loc) · 3.36 KB
/
render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
var fs = require("fs"),
async = require("async"),
dot = require("dot"),
extractMetadata = require("json-finder")(),
hl = require("highlight").Highlight,
parseMarkdown = require("marked").setOptions({
gfm: true, // Github flavored Markdown
highlight: hl
});
function generateSummary(html) {
var firstParagraph = html.search("</p>") + 4;
return html.substr(0, firstParagraph);
}
function generatePost(path, callback) {
fs.readFile("posts/" + path, "utf-8", function(err, rawFile) {
if (err) { return callback(err); }
extractMetadata(rawFile, function(err, article, start, end) {
article.html = parseMarkdown(rawFile.slice(end));
article.summary = generateSummary(article.html);
article.link = path.substr(0, path.length - 3);
callback(null, article);
});
});
}
function indexArticles(callback) {
// Helpers
function readAllPosts(data, callback) {
async.map(data, generatePost, callback);
}
function sortByDate(articles, callback) {
function iterator(obj, callback) {
if (obj.date) {
return callback(null, obj.date);
}
return callback(new Error("Article has no date."));
}
// Note that this sorts in reverse lexicographical order!
// hence the sorted.reverse() at the end
async.sortBy(articles, iterator, function(err, sorted) {
if (err) { return callback(err); }
callback(err, {"articles": sorted.reverse()});
});
}
async.waterfall([
async.apply(fs.readdir, "posts/"),
async.apply(readAllPosts),
async.apply(sortByDate)
], async.apply(callback));
}
function compileTemplate(template, callback) {
async.waterfall([
async.apply(fs.readFile, "templates/" + template + ".dot"),
function(data, callback) { callback(null, dot.template(data)); }
], async.apply(callback));
}
module.exports = {
home: function(callback) {
async.parallel({
"template": async.apply(compileTemplate, "index"),
"posts": async.apply(indexArticles)
}, function(err, results) {
if (err) {
callback(err);
} else {
callback(null, results.template(results.posts));
}
});
},
article: function(req, res, callback) {
async.parallel({
"template": async.apply(compileTemplate, "article"),
"post": async.apply(generatePost, req.params.article + ".md")
}, function(err, results) {
if (err) {
callback(err);
} else {
callback(null, results.template(results.post));
}
});
},
json: function(req, res, callback) {
var filepath = "posts/" + req.params.article + ".md";
fs.readFile(filepath, "utf-8", function(err, rawFile) {
if (err) {
callback(err);
} else {
extractMetadata(rawFile, function(err, article, start, end) {
if (err) {
callback(err);
} else {
article.content = rawFile.slice(end);
callback(null, JSON.stringify(article));
}
});
}
});
}
};