jsheader
Version:
Generates headers for files
231 lines (184 loc) • 5.89 kB
JavaScript
/*
SPECIFICATION FOR CONFIG FILE:
JSON file with fields:
- Mandatory:
- header: String
- Optional:
- directory: String. Uses pwd as default. Root directory of the project
- exclude: Array<String>. The strings must be regexes (without the //), excludes paths that match
- headerTest: String. Stringifed regex (without //). Used to match old headers
- extension: Array<String>. Extensions of the files to modify. Default: ['js', 'jsx']
*/
const path = require('path');
const fs = require('fs');
// Getting config
const configFile = process.argv[2];
if (!configFile) { throw 'Config file not provided'; }
const config = (() => {
const config = {};
try {
const configFileContent = JSON.parse(fs.readFileSync(configFile).toString());
if (!configFileContent.header) {
throw `Configuration not valid: missing parameter header`;
}
// Building regex for excluded
config.exclude = configFileContent.exclude &&
configFileContent.exclude.map &&
configFileContent.exclude.map((e) => new RegExp(e))
|| [];
// Adding directory
if (!configFileContent.directory) {
// No directory provided, using pwd
try {
const pwd = /^(.*\/)(?:[^\/]*)$/.exec(process.argv[1])[1];
if (pwd.length > 1) {
config.directory = pwd;
}
else { throw 1; }
}
catch (e) {
throw `Directory not provided and could not determine the present working directory`;
}
}
else {
config.directory = configFileContent.directory;
}
// Adding header
config.header = configFileContent.header + '';
// Extension
config.extension = configFileContent.extension && configFileContent.extension.constructor === Array
? configFileContent.extension
: ['js', 'jsx'];
config.extension = config.extension.map((extension) => new RegExp(`.${extension}$`));
// Pattern for detecting header (detects any /** */ that has @license */
const detectHeaderDefault = /^\/(.|\n)+?@license(.|\n)+?\*\/[\n]*/;
config.detectHeader = configFileContent.headerTest
? new RegExp(configFileContent.headerTest)
: detectHeaderDefault;
return config;
}
catch (e) {
console.log(`Could not use config file.`);
console.log(e);
process.exit();
}
})();
// Printing settings
console.log(`Header to be written:`);
console.log(`=== START ===`);
console.log(config.header);
console.log(`=== END ===`);
console.log('');
console.log(`Files directory: ${config.directory}`);
console.log('');
console.log(`File extension: ${config.extension}`);
console.log('');
console.log('Test for exclusion:');
config.exclude.forEach((e) => console.log(`- ${e.toString()}`));
console.log('');
console.log(`Test for detecting old headers: ${JSON.stringify(config.detectHeader.toString())}`);
console.log('');
// Getting files in the directory
let files = (function () {
const files = [];
const rootPath = config.directory;
readDir([ rootPath ]);
function readDir(path = []) {
const stringPath = path.join('/');
const dirFiles = fs.readdirSync(stringPath);
dirFiles.forEach((file) => {
const thisPathString = [ ...path, file ].join('/');
const isDirectory = fs.lstatSync(thisPathString).isDirectory();
// Invalid path
if (!allowedPath(thisPathString)) { return; }
if (isDirectory) {
readDir([ ...path, file ]);
}
else {
// Invalid extension
if (!allowedExtension(thisPathString)) { return; }
files.push(thisPathString);
}
});
}
return files;
})();
if (files.length < 1) {
console.log('No files matched!');
process.exit();
}
console.log(`${files.length} files found:`);
files.forEach(file => console.log(`- ${file}`));
console.log('\nDo you want to continue? (y/n)');
process.stdin.on('data', (input) => {
input = (input + '').replace(/[ \n]/g, '').toLowerCase();
if (input === 'y') {
console.log('Writing headers');
// Writing headers on every file
Promise
.all(files.map(file => writeHeader(file)))
.then(() => {
console.log('All done');
process.exit();
})
.catch((err) => {
console.log(err);
process.exit();
});
}
else {
console.log('Canceled');
process.exit();
}
});
/**
* Writes the header to a file
* @return {Promise}
*/
function writeHeader(file) {
return new Promise((resolve) => {
const existingDataBuffer = fs.readFileSync(file);
// Removing old headers
const newData = config.header + existingDataBuffer
.toString()
.replace(config.detectHeader, '');
const handler = fs.openSync(file, 'w+');
// Writing new data
fs.writeFile(file, newData, () => {
fs.close(handler);
resolve();
});
});
}
/**
* Tests if a path is allowed or not
* @return {Boolean}
*/
function allowedPath(path) {
// Empty path
if (path.length < 1) { return false; }
return config.exclude.reduce((result, test) => {
// We matched the pattern, so the path is not allowed
if (test.test(path)) {
return false;
}
return result;
}, true);
}
/**
* Tests if an extension is allowed
* @return {Boolean}
*/
function allowedExtension(path) {
// Empty path
if (path.length < 1) { return false; }
// No filters
if (config.extension.length < 1) { return true; }
return config.extension.reduce((result, test) => {
// We did match the pattern, so the path is allowed
if (test.test(path)) {
return true;
}
return result;
}, false);
}