2014-02-17 20:34:24 +04:00
|
|
|
var _ = require('lodash'),
|
2014-02-09 01:16:58 +04:00
|
|
|
fs = require('fs'),
|
2014-02-17 20:34:24 +04:00
|
|
|
keys = require('when/keys'),
|
2014-02-09 01:16:58 +04:00
|
|
|
path = require('path'),
|
2014-02-17 20:34:24 +04:00
|
|
|
when = require('when'),
|
2014-02-28 23:52:32 +04:00
|
|
|
parsePackageJson = function (path, messages) {
|
|
|
|
// Default the messages if non were passed
|
|
|
|
messages = messages || {
|
|
|
|
errors: [],
|
|
|
|
warns: []
|
|
|
|
};
|
|
|
|
|
2014-02-09 01:16:58 +04:00
|
|
|
var packageDeferred = when.defer(),
|
|
|
|
packagePromise = packageDeferred.promise,
|
|
|
|
jsonContainer;
|
|
|
|
|
|
|
|
fs.readFile(path, function (error, data) {
|
|
|
|
if (error) {
|
2014-03-23 21:22:05 +04:00
|
|
|
messages.errors.push({
|
|
|
|
message: 'Could not read package.json file',
|
|
|
|
context: path
|
|
|
|
});
|
2014-02-09 01:16:58 +04:00
|
|
|
packageDeferred.resolve(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
jsonContainer = JSON.parse(data);
|
|
|
|
if (jsonContainer.hasOwnProperty('name') && jsonContainer.hasOwnProperty('version')) {
|
|
|
|
packageDeferred.resolve(jsonContainer);
|
|
|
|
} else {
|
2014-03-23 21:22:05 +04:00
|
|
|
messages.errors.push({
|
|
|
|
message: '"name" or "version" is missing from theme package.json file.',
|
|
|
|
context: path,
|
|
|
|
help: 'This will be required in future. Please see http://docs.ghost.org/themes/'
|
|
|
|
});
|
2014-02-09 01:16:58 +04:00
|
|
|
packageDeferred.resolve(false);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2014-03-23 21:22:05 +04:00
|
|
|
messages.errors.push({
|
|
|
|
message: 'Theme package.json file is malformed',
|
|
|
|
context: path,
|
|
|
|
help: 'This will be required in future. Please see http://docs.ghost.org/themes/'
|
|
|
|
});
|
2014-02-09 01:16:58 +04:00
|
|
|
packageDeferred.resolve(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return when(packagePromise);
|
|
|
|
},
|
2014-02-28 23:52:32 +04:00
|
|
|
readDir = function (dir, options, depth, messages) {
|
2013-06-25 15:43:15 +04:00
|
|
|
depth = depth || 0;
|
2014-02-28 23:52:32 +04:00
|
|
|
messages = messages || {
|
|
|
|
errors: [],
|
|
|
|
warns: []
|
|
|
|
};
|
2013-06-09 20:45:17 +04:00
|
|
|
|
2014-02-17 20:34:24 +04:00
|
|
|
options = _.extend({
|
2013-06-25 15:43:15 +04:00
|
|
|
index: true
|
|
|
|
}, options);
|
2013-06-09 20:45:17 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
if (depth > 1) {
|
|
|
|
return null;
|
|
|
|
}
|
2013-06-09 20:45:17 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
var subtree = {},
|
|
|
|
treeDeferred = when.defer(),
|
|
|
|
treePromise = treeDeferred.promise;
|
2013-06-15 18:20:30 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
fs.readdir(dir, function (error, files) {
|
|
|
|
if (error) {
|
|
|
|
return treeDeferred.reject(error);
|
|
|
|
}
|
2013-06-15 18:20:30 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
files = files || [];
|
2013-06-09 20:45:17 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
files.forEach(function (file) {
|
|
|
|
var fileDeferred = when.defer(),
|
|
|
|
filePromise = fileDeferred.promise,
|
|
|
|
fpath = path.join(dir, file);
|
2014-02-09 01:16:58 +04:00
|
|
|
subtree[file] = filePromise;
|
2013-06-25 15:43:15 +04:00
|
|
|
fs.lstat(fpath, function (error, result) {
|
2013-10-31 22:02:34 +04:00
|
|
|
/*jslint unparam:true*/
|
2013-06-25 15:43:15 +04:00
|
|
|
if (result.isDirectory()) {
|
2014-02-28 23:52:32 +04:00
|
|
|
fileDeferred.resolve(readDir(fpath, options, depth + 1, messages));
|
2014-03-23 21:22:05 +04:00
|
|
|
} else if (depth === 1 && file === 'package.json') {
|
2014-02-28 23:52:32 +04:00
|
|
|
fileDeferred.resolve(parsePackageJson(fpath, messages));
|
2013-06-25 15:43:15 +04:00
|
|
|
} else {
|
|
|
|
fileDeferred.resolve(fpath);
|
|
|
|
}
|
2013-06-09 20:45:17 +04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-07-31 12:21:22 +04:00
|
|
|
return keys.all(subtree).then(function (theFiles) {
|
2013-06-25 15:43:15 +04:00
|
|
|
return treeDeferred.resolve(theFiles);
|
2013-06-09 20:45:17 +04:00
|
|
|
});
|
2013-06-25 15:43:15 +04:00
|
|
|
});
|
|
|
|
|
|
|
|
return when(treePromise).then(function (prom) {
|
|
|
|
return prom;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
readAll = function (dir, options, depth) {
|
2014-02-28 23:52:32 +04:00
|
|
|
// Start with clean messages, pass down along traversal
|
|
|
|
var messages = {
|
|
|
|
errors: [],
|
|
|
|
warns: []
|
|
|
|
};
|
|
|
|
|
|
|
|
return when(readDir(dir, options, depth, messages)).then(function (paths) {
|
2014-02-09 01:16:58 +04:00
|
|
|
// for all contents of the dir, I'm interested in the ones that are directories and within /theme/
|
2014-03-23 21:22:05 +04:00
|
|
|
if (typeof paths === 'object' && dir.indexOf('theme') !== -1) {
|
2014-02-09 01:16:58 +04:00
|
|
|
_.each(paths, function (path, index) {
|
|
|
|
if (typeof path === 'object' && !path.hasOwnProperty('package.json') && index.indexOf('.') !== 0) {
|
2014-03-23 21:22:05 +04:00
|
|
|
messages.warns.push({
|
|
|
|
message: 'Found a theme with no package.json file',
|
|
|
|
context: 'Theme name: ' + index,
|
|
|
|
help: 'This will be required in future. Please see http://docs.ghost.org/themes/'
|
|
|
|
});
|
2014-02-09 01:16:58 +04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
paths._messages = messages;
|
2013-06-25 15:43:15 +04:00
|
|
|
return paths;
|
2014-03-26 02:38:48 +04:00
|
|
|
}).otherwise(function () {
|
|
|
|
return {'_messages': messages};
|
2013-06-25 15:43:15 +04:00
|
|
|
});
|
|
|
|
};
|
2013-06-09 20:45:17 +04:00
|
|
|
|
2014-02-28 23:52:32 +04:00
|
|
|
module.exports = {
|
|
|
|
readAll: readAll,
|
|
|
|
readDir: readDir,
|
|
|
|
parsePackageJson: parsePackageJson
|
|
|
|
};
|