gitbook-summary
Version:
A CLI to generate a summary from a given folder.
210 lines (173 loc) • 5.95 kB
JavaScript
var _ = require("lodash");
var color = require('bash-color');
var fs = require('fs');
var path = require('path');
var async = require('async');
var bookJson = require('../bookJson');
var utils = require('../utils');
var readFile = require('../files').readFile;
/**
* Get a summary from a fold such as `/path/to/your/book` or `../book`
* @param root path
*/
// Give some variables
var root,
title, // todo: don`t use `name`?
outputFile,
catalog,
ignores,
unchanged,
sortedBy,
disableTitleFormatting;
// Get options
function init(options) {
root = options.root || '.';
var bookConfig = bookJson(root);
utils.rewrite(options, bookConfig);
outputFile = options.outputfile || bookConfig.outputfile;
catalog = options.catalog || bookConfig.catalog;
ignores = options.ignores || bookConfig.ignores;
unchanged = options.unchanged || bookConfig.unchanged;
title = options.title || bookConfig.title;
sortedBy = options.sortedBy || bookConfig.sortedBy;
disableTitleFormatting = options.disableTitleFormatting || bookConfig.disableTitleFormatting;
}
// Get summary
function Summary(options) {
var result = '',
desc = '',
step = 0,
skip = null,
filesObj;
async.auto({
init: function(next) {
init(options);
// Ignore the outputFile, for example `SUMMARY`
ignores.push(_.trim(outputFile, '.md'));
next();
},
files: ['init', function(next) {
filesObj = getFiles(root);
if (filesObj) {
next();
} else {
next(color.red("Sorry, something is going wrong or no markdowns."));
}
}],
parse: ['files', function(next) {
work(filesObj);
next();
}],
write: ['parse', function(next) {
title = "# " + title + "\n\n";
result += title + desc;
writeFile(outputFile, result);
}]
}, function(err, results) {
console.log(err);
});
function work(filesObj) {
_.forEach(filesObj, function(n, key) {
if (!_.includes(ignores, key)) {
if (_.isObject(n)) {
// It means folderName == subFileName, for example: */assets/assets.md or */Assets/assets.md
if (_.isString(n[key]) || _.isString(n[key.toLowerCase()])) {
var file = n[key] || n[key.toLowerCase()];
desc += _.repeat(' ', step) + formatCatalog(key, '-') + file;
// Mark it to skip
skip = key;
}
// The file is `readme.md`
else if (_.isString(n['readme']) || _.isString(n['Readme']) || _.isString(n['README'])) {
var readmeDir = n['readme'] || n['Readme'] || n['README'];
desc += _.repeat(' ', step) + formatCatalog(key, '-') + readmeDir.replace(" ", "%20");
} else {
desc += _.repeat(' ', step) + "- " + prettyCatalogName(key) + "\n";
}
// Start a loop
step += 2;
work(n);
step -= 2;
} else {
// Skip if `skip` exists or key == `readme`
if (isSkiped(key, skip)) {
return;
}
desc += _.repeat(' ', step) + formatCatalog(key) + n.replace(" ", "%20");
}
}
});
}
}
// Get a filesJson Object
function getFiles(root) {
var result = null,
filesJson = {};
readFile(root, filesJson, sortedBy);
if (filesJson) {
result = _.pick(filesJson, filterRules);
}
return result;
}
// Filter in the `catalog` and exclude in the `ignores`
function filterRules(n, key) {
var result = null;
// Ignore hidden files, for example `.git`
if (/^[\.]\w*|_book|node_modules/.test(key)) {
ignores.push(key);
}
if (catalog === 'all') {
result = !_.includes(ignores, key);
} else {
result = _.includes(catalog, key) && !_.includes(ignores, key);
}
return result;
}
// Sign is `-` when folders, `*` when files
function formatCatalog(folderName, sign) {
sign = sign || '*';
return sign + " [" + prettyCatalogName(folderName) + "](";
}
function prettyCatalogName(fileName) {
// Sorted if given a sorted hyphen, for example: `-` or `_`
if (sortedBy) {
var pattern = "^[\\da-zA-Z]*" + sortedBy;
var reg = RegExp(pattern);
if (reg.test(fileName)) {
var folderNameReg = new RegExp(pattern + "(.*)");
fileName = fileName.match(folderNameReg)[1];
}
}
// Don`t format the files like `req.options.*` using dot, unchanged or Chinese string.
if (_.size(fileName.split(".")) > 1 || _.includes(unchanged, fileName) || isChinese(fileName) ||
disableTitleFormatting || isNonAscii(fileName)) {
return fileName;
}
return _.startCase(fileName);
}
function isChinese(string) {
var req = /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi;
if (!req.exec(string)) {
return false;
} else {
return true;
}
}
function isNonAscii(string) {
var regExp = /^[ -~\t\n\r]+$/gi;
return !regExp.test(string);
}
function isSkiped(key, skip) {
var result = !_.isEmpty(skip) && _.isEqual(key.toLowerCase(), skip.toLowerCase()) || _.isEqual(key.toLowerCase(), 'readme');
return result;
}
// Write to file encoded with utf-8
function writeFile(fileName, data) {
fs.writeFile(fileName, data, 'utf-8', function() {
console.log(color.green("Finished, generated '"+fileName+"' successfully."));
});
}
module.exports = {
summary: Summary,
isNonAscii: isNonAscii
};