This repository has been archived by the owner on Nov 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
377 lines (303 loc) · 12.5 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
"use strict";
/**
* Created by sbusse on 30.09.2014.
*/
var _ = require("underscore");
var Path = require("path");
var Fs = require("fs");
var ncp = require('ncp').ncp;
var ModuleUtils = require("punch/lib/utils/module_utils");
module.exports = {
contentDir: null,
outputDir: null,
filesDirectories: [],
parsers: {},
setup: function (config) {
var self = this;
self.contentDir = config.content_dir;
self.outputDir = config.output_dir;
self.filesDirectories = config.files_dir;
_.each(config.plugins.parsers, function (value, key) {
var parser = ModuleUtils.requireAndSetup(value, config);
var extensions = _.union([key], (parser.supportedExtensions || []));
_.each(extensions, function (extension) {
self.parsers[extension] = parser;
});
});
},
isSection: function (content_path) {
var self = this;
if (!content_path) {
return false;
}
var path_portions = content_path.split(Path.sep || "/");
if (_.any(path_portions, function (portion) {
return ( [".", "_"].indexOf(portion[0]) > -1 );
}) || self.checkForFDir(content_path)) {
return false;
}
var stat;
try {
stat = Fs.statSync(Path.join(self.contentDir, content_path));
} catch (e) {
//gotcha!
}
return stat && stat.isDirectory();
},
parseExtendedContent: function (basePath, callback) {
var self = this;
var extended_dir_path = function () {
var path_portions = basePath.split(Path.sep || "/");
path_portions.push("_" + path_portions.pop().replace("/", ""));
path_portions.unshift(self.contentDir);
return Path.join.apply(null, path_portions);
};
var getParserFor = function (extension) {
return self.parsers[extension];
};
var jsonParse = function (input, callback) {
return callback(null, JSON.parse(input));
};
var parseFile = function (file_path, callback) {
// check if there's a parser supporting the given extension
var basename = Path.basename(file_path).split(".");
var file_extension = "." + basename.pop();
var parser;
if (file_extension === ".json") {
parser = { "parse": jsonParse };
} else {
parser = getParserFor(file_extension);
}
if (parser) {
Fs.stat(file_path, function (err, stat) {
if (err) {
return callback(err);
}
var modified_date = stat.mtime;
Fs.readFile(file_path, function (err, file_output) {
if (err) {
return callback(err);
}
parser.parse(file_output.toString(), function (err, parsed_output) {
if (err) {
return callback(err, basename.shift(), null, modified_date);
}
return callback(null, basename.shift(), parsed_output, modified_date);
});
});
});
} else {
return callback("no parser found");
}
};
var parsed_contents = {};
var last_modified = null;
// go through each file in the directory and parse them
Fs.readdir(extended_dir_path(), function (err, files) {
if (err) {
return callback(err, null, null);
}
// filter the hidden files
var content_files = [];
_.each(files, function (file) {
if (file[0] !== ".") {
content_files.push(Path.join(extended_dir_path(), file));
}
});
// parse each file
var parse_file_callback = function (err, content_name, parsed_content, modified_date) {
if (!err) {
parsed_contents[content_name] = parsed_content;
if (modified_date > last_modified) {
last_modified = modified_date;
}
}
if (content_files.length) {
return parseFile(content_files.pop(), parse_file_callback);
} else {
return callback(null, parsed_contents, last_modified);
}
};
parseFile(content_files.pop(), parse_file_callback);
});
},
getContent: function (basePath, callback) {
var self = this;
var content_output = {};
var last_modified = null;
var getJSONFile = function (file_path, callback) {
Fs.stat(file_path, function (err, stat) {
if (err) {
return callback(err);
}
Fs.readFile(file_path, function (err, file_output) {
if (err) {
return callback(err);
}
var parsed_json, error;
try {
parsed_json = file_output.length ? JSON.parse(file_output) : "";
} catch (err) {
error = err;
}
return callback(error, parsed_json, stat.mtime);
});
});
};
// look for the JSON file in the path
var json_file = Path.join(self.contentDir, basePath) + ".json";
getJSONFile(json_file, function (json_err, json_output, modified_date) {
if (!json_err) {
content_output = _.extend(content_output, json_output);
last_modified = modified_date;
}
// look for extended content
self.parseExtendedContent(basePath, function (extended_err, extended_output, extended_modified_date) {
if (!extended_err) {
content_output = _.extend(content_output, extended_output);
if (extended_modified_date > last_modified) {
last_modified = extended_modified_date;
}
}
if (json_err && extended_err) {
return callback("[Error] No content found", null, last_modified);
} else {
return callback(null, content_output, last_modified);
}
});
});
},
getSharedContent: function (callback) {
var self = this;
return self.getContent("shared", callback);
},
checkForFDir: function(path) {
var basePathSplit = path.split(Path.sep || "/");
var lastBasePath = basePathSplit[basePathSplit.length-1];
var isFDir = _.any(this.filesDirectories, function(fDir) {
return (lastBasePath == fDir);
});
return isFDir;
},
// returns all available sections rooting from the given path
getSections: function (callback) {
var self = this;
var sections = [Path.join("/")];
var paths_to_traverse = [];
var should_exclude = function (entry) {
var isFDir = self.checkForFDir(entry);
return entry[0] === "." || entry[0] === "_" || entry === "shared" || isFDir;
};
var traverse_path = function () {
var current_path = paths_to_traverse.shift() || "";
Fs.readdir(Path.join(self.contentDir, current_path), function (err, entries) {
if (err) {
throw err;
}
var run_callbacks = function () {
if (entries.length) {
return next_entry();
} else if (paths_to_traverse.length) {
return traverse_path();
} else {
return callback(sections);
}
};
var next_entry = function () {
var current_entry = entries.shift();
if (should_exclude(current_entry)) {
return run_callbacks();
}
var current_entry_path = Path.join(current_path, current_entry);
Fs.stat(Path.join(self.contentDir, current_entry_path), function (err, stat) {
if (err) {
return run_callbacks();
}
if (stat.isDirectory()) {
sections.push(Path.join("/", current_entry_path));
paths_to_traverse.push(current_entry_path);
}
return run_callbacks();
});
};
return run_callbacks();
});
};
return traverse_path();
},
// returns all available content paths under a given section path
getContentPaths: function (basePath, callback) {
var self = this;
var collected_contents = [];
if (!basePath) {
return callback("base path can't be null", []);
}
// try to read the given path dir
Fs.readdir(Path.join(self.contentDir, basePath), function (err, files) {
if (err) {
return callback(err, []);
}
_.each(files, function (file) {
if (file.indexOf(".") > 0 || file[0] === "_") {
var basename;
// given entry is a extended directory
if (file[0] === "_") {
basename = file.substr(1);
} else {
// given entry is a JSON file
var path_portions = file.split(".");
path_portions.pop(); //remove the final extension
basename = path_portions.join(".");
}
var full_path = Path.join(basePath, basename);
if (basename !== "shared" && collected_contents.indexOf(full_path) < 0) {
collected_contents.push(full_path);
}
}else {
if(self.checkForFDir(file)) {
console.log("copy folder: " + Path.join(basePath, file) + " to: " + self.outputDir);
ncp(Path.join(self.contentDir, basePath, file), Path.join(self.outputDir, basePath, file), function (err) {
if (err) {
return console.error(err);
}
});
}
}
});
return callback(null, collected_contents);
});
},
// provide the best matching content for the given arguments
negotiateContent: function (basePath, output_extension, options, callback) {
var self = this;
var collected_contents = {};
var content_options = {};
var last_modified = null;
// treat files with special output extensions
if (output_extension !== ".html") {
basePath = basePath + output_extension;
}
self.getContent(basePath, function (err, contents, modified_date) {
if (!err) {
collected_contents = _.extend(collected_contents, contents);
last_modified = modified_date;
var run_callback = function () {
return callback(null, collected_contents, content_options, last_modified);
};
//fetch shared content
self.getSharedContent(function (err, shared_content, shared_modified_date) {
if (!err) {
collected_contents = _.extend(shared_content, collected_contents);
if (shared_modified_date > last_modified) {
last_modified = shared_modified_date;
}
Fs.writeFileSync(Path.join(self.outputDir, "json", basePath + ".json"), JSON.stringify(collected_contents), {encoding: "utf8"});
}
return run_callback();
});
} else {
return callback("[Error: Content for " + basePath + " not found]", null, null, {});
}
});
}
};