/
index.js
136 lines (114 loc) · 3.29 KB
/
index.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
(function () {
var _ = require('lodash')
, fs = require('fs')
, path = require('path')
, yaml = require('js-yaml')
, async = require('async')
, kitten
, mdExts = ['md', 'mdown', 'markdown']
, requiredFields = [
'layout'
, 'title'
, 'date'
]
, defaults = {
published: true
, categories: []
};
kitten = {
load: function (path, cb) {
fs.stat(path, function (err, stat) {
if(err) {
return cb(err, null);
}
if(stat.isFile()) {
kitten._loadFile(path, cb);
}
else {
kitten._loadDirectory(path, cb);
}
});
}
, _loadFile: function (file, cb) {
fs.readFile(file, function (err, data) {
var resp
, header
, content
, basename = path.basename(file)
, errorLoadingText = 'Error loading ' + basename + ': ';
if(err) {
return cb(errorLoadingText + err, null);
}
// Convert buffer to string
data = data.toString();
// Find the YAML header
header = data.match(/^---(.|\s)+?(?=---)/);
if(!header) {
return cb(errorLoadingText + 'No YAML header found', null);
}
// Find the post content
content = data.substring(data.lastIndexOf('---') + 3).trim();
// Remove '---'; JS has no negative lookbehind ):
header = header[0].substring(3).trim();
// Parse the header
try {
header = yaml.safeLoad(header);
}
catch (e) {
return cb(errorLoadingText + 'The YAML header was malformed (' + e + ')', null);
}
// Check for required fields
for(var i=0, ii=requiredFields.length; i<ii; i++) {
if(header[requiredFields[i]] == null) {
return cb(errorLoadingText + 'The YAML header is missing the required ' + requiredFields[i] + ' field');
}
}
// Set defaults
header = _.extend({}, defaults, header);
// Parse `date` into a javascript Date object
header.date = new Date(header.date);
// Make sure `published` is a bool
header.published = (header.published == 'true' || header.published === true);
cb(null, _.extend({}, header, {content: content}));
});
}
, _loadDirectory: function (directory, cb) {
var self = this
, basename = path.basename(directory)
, errorLoadingText = 'Error loading ' + basename + ': '
, loaders = {};
fs.readdir(directory, function (err, files) {
if(err) {
return cb(errorLoadingText + err, null);
}
files = _.filter(files, function (filePath) {
// Returns true if file extension is a known markdown alias
return mdExts.indexOf(filePath.split('.').pop().toLowerCase()) >= 0;
});
_.each(files, function (filePath) {
var fullPath = path.join(directory, filePath)
, baseName = path.basename(fullPath);
loaders[baseName] = function (next) {
self._loadFile(fullPath, function (err, data) {
if(err) {
next(err);
}
else {
next(null, data);
}
});
};
});
async.series(loaders, function (err, data) {
if(err) {
cb(err, null);
}
else {
cb(null, data);
}
});
});
}
};
module.exports = kitten;
}());