Hexo命令行入口

在开始用Hexo时,第一步就是全局安装hexo-cli模块
这是Hexo的命令行入口,通过这个模块可以顺藤摸瓜找到Hexo的核心

hexo-cli的结构比较简单,起点bin目录,这样就可以在命令行下使用hexo命令
hexo命令实际上进入了lib下的hexo.js文件

bin/hexo
1
require('../lib/hexo')();

每次敲击一条命令,首先会定位当前路径,解析传入参数,并建立一个Context对象
Context对象其实是Hexo模块的简易版,如果之后成功加载了主模块,那么这个变量将会替换

1
2
3
cwd = cwd || process.cwd();
args = camelCaseKeys(args || minimist(process.argv.slice(2)));
var hexo = new Context(cwd, args);

然后会在当前路径下寻找package.json
如果找到并包含名为Hexo的key,那么这个路径就是工作目录的路径
没找到的话会重新找父路径,所以即使深入到工作路径下的子文件夹,依然可以执行hexo命令

lib/find_pkg.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function checkPkg(path) {
var pkgPath = pathFn.join(path, 'package.json');

return fs.readFile(pkgPath).then(function(content) {
var json = JSON.parse(content);
if (typeof json.hexo === 'object') return path;
}).catch(function(err) {
if (err && err.cause.code === 'ENOENT') {
var parent = pathFn.dirname(path);

if (parent === path) return;
return checkPkg(parent);
}

throw err;
});
}

也可以不从当前路径开始找起,可以通过cwd参数指定一个路径

lib/find_pkg.js
1
2
3
4
5
6
7
function findPkg(cwd, args) {
args = args || {};
if (args.cwd) {
cwd = pathFn.resolve(cwd, args.cwd);
}
return checkPkg(cwd);
}

确定工作路径后会尝试加载node_modules中的Hexo主模块

lib/hexo.js
1
2
3
4
5
6
7
8
function loadModule(path, args) {
return Promise.try(function() {
var modulePath = pathFn.join(path, 'node_modules', 'hexo');
var Hexo = require(modulePath);

return new Hexo(path, args);
});
}

之后会进行主模块替换,初始化console以及初始化hexo
初始化console会在主模块中注册3个命令,分别为help,init和version
这三个命令是全局命令,在哪个目录,都可以执行

1
2
3
4
if (mod) hexo = mod;
log = hexo.log;
require('./console')(hexo);
return hexo.init();

接下来会查找命令,如果找不到就通通转化成help命令

1
2
3
4
5
6
7
8
9
10
11
12
13
var cmd = '';
if (!args.h && !args.help) {
cmd = args._.shift();

if (cmd) {
var c = hexo.extend.console.get(cmd);
if (!c) cmd = 'help';
} else {
cmd = 'help';
}
} else {
cmd = 'help';
}

最后就是调用命令执行,完成了整条链路~

1
return hexo.call(cmd, args)

彩蛋:如果使用Ctrl+C终止Hexo, 会随机显示一条结束语

lib/goodbye.js
1
2
3
4
5
6
7
8
9
10
11
var byeWords = [
'Good bye',
'See you again',
'Farewell',
'Have a nice day',
'Bye!',
'Catch you later'
];
module.exports = function() {
return byeWords[(Math.random() * byeWords.length) | 0];
};