ismart-doc
Version:
API documentation generator,base in https://github.com/mhbseal/modoc
131 lines (113 loc) • 4.54 kB
JavaScript
var
fs = require('fs'),
path = require('path'),
_ = require('underscore'),
data = [],
result = {},
skipDir = [],
configPath = './ismart.config.js',
tpl, filenames, matchs, name, html, eachFile, fixDir, config, srcPath, distPath;
var defaultConfig = {
}
// 读取目录
process.argv.forEach(function (argv, i) {
if (argv === '--config') {
configPath = process.argv[i + 1];
}
});
// 读取config内容
try {
config = require(path.join(process.cwd(), configPath)).doc;
} catch (e) {
console.log('config missing');
return;
}
// 路径
srcPath = config.paths.input;
distPath = config.paths.output;
// 排除目录矫正
_.each(config.skip, function (v) {
skipDir.push(path.join(srcPath, v))
});
// 遍历src文件夹读取js
eachFile = function (dir) {
filenames = fs.readdirSync(dir);
filenames.forEach(function (filename) {
fixDir = path.join(dir, filename);
if (~skipDir.indexOf(fixDir)) { // 如果目录等于config中的排除目录直接跳过
return;
} else {
if (path.extname(filename) !== '') {
data.push(fs.readFileSync(fixDir, {encoding: 'utf8'}));
// file dir log
console.log(fixDir + '......loading');
} else if (filename !== '.DS_Store') {
eachFile(fixDir);
}
}
})
};
// 读取数据
tpl = fs.readFileSync(path.join(__dirname, 'template.html'), {encoding: 'utf8'});
eachFile(srcPath);
// 读取注释
data.forEach(function (text) { // 循环文件
matchs = text.match(/\/\*\*[^*][\s\S]*?\*\//g);
if (!matchs) { // 跳过不需要生成doc的js文件
return;
}
var
singleResult = {items: []},
singleName;
matchs.forEach(function (match, i) {
// 循环文件中的注释
singleResult['items'][i - 1] = {params: []};
match.replace(/@(name|grammar|param|params|return|example|more)\s+(?:\{(.*)\})?\s*([^@]*)|\/\*\*[*\s]+([^@]+)/gi, function ($0, $1, $2, $3, $4) {
if ($1) { // 非描述信息
$1 = $1.toLowerCase();
$3 = $3.replace(/[\t ]*\*[\t ]?|(?:\s*\*[\s\/]*)*$/g, ''); // reg => 多行处理|去掉$3后面没用的
if (i === 0) { // js文件顶部注释信息
if ($1 === 'name') { // name直接作为data的key存储此文件的内容
singleName = $3;
} else {
singleResult[$1] = $3;
}
} else { // 非顶部注释
if ($1 === 'name' || $1 === 'grammar') { // name/grammar
singleResult['items'][i - 1][$1] = $3;
} else {
if ($1 === 'example' || $1 === 'more') { // example/more
singleResult['items'][i - 1][$1] = $3;
} else { // param/return
singleResult['items'][i - 1]['params'].push([$1, $2, $3]);
}
}
}
} else { // 描述
$4 = $4.replace(/[\t ]*\*[\t ]?|(?:\s*\*[\s\/]*)*$/g, ''); // reg => 多行处理|去掉$3后面没用的
if (i === 0) {
singleResult['desc'] = $4;
} else {
singleResult['items'][i - 1]['desc'] = $4;
}
}
})
});
if (singleName) result[singleName] = singleResult;
})
// 模板渲染
html = _.template(tpl)({config: config, data: result});
// 创建生成目录
!fs.existsSync(distPath) && fs.mkdirSync(distPath);
!fs.existsSync(path.join(distPath, 'images')) && fs.mkdirSync(path.join(distPath, 'images'));
!fs.existsSync(path.join(distPath, 'javascripts')) && fs.mkdirSync(path.join(distPath, 'javascripts'));
// 生成doc
fs.writeFileSync(path.join(distPath, 'index.html'), html);
// 生成html需要的image
fs.writeFileSync(path.join(distPath, 'images/background.png'), fs.readFileSync(path.join(__dirname, 'images/background.png')));
// 生成目标js,便于控制台即调用
if (config.source) {
fs.writeFileSync(path.join(distPath, 'javascripts', config.name + '.js'), fs.readFileSync(config.source));
}
// success log
console.log('all success!')