savvy-js
Version:
Savvy - Style sheet documentation tool
181 lines (156 loc) • 5.84 kB
JavaScript
/**
* The fileReader finds files in given paths and reads them.
*
* @class fileReader
* @namespace savvy
*/
(function () {
'use strict';
var Minimatch = require('minimatch').Minimatch,
fs = require('fs');
/**
* Get a flat list of files from a given folders, that match a specific patten.
*
* var fileReader = require('./fileReader'),
* sassFiles = fileReader.getFiles('c:/workspace/sass', '*.scss', { matchBase: true });
*
* This uses the Minimatch library, see more details on possible patterns at https://github.com/isaacs/minimatch.
*
* @method getFiles
* @param {string | []} folders - a folder path or collection of folder paths. All files inside them will be
* evaluated using Minimatch pattern.
* @param {function} callback
* @param {string} [pattern] - A pattern that matches the files you wish to get.
* @param {object} [options] - Pattern matching options. See more details at https://github.com/isaacs/minimatch
*/
function getFiles (folders, callback, pattern, options) {
var files = [],
foldersProcessed,
test;
function processFiles(files){
return matchPattern(test, files);
}
function folderReadCallback(err, resultFiles){
if(err){
callback(err, null);
}
else{
files = files.concat(resultFiles);
foldersProcessed = foldersProcessed - 1;
if(!foldersProcessed){
callback(null, files);
}
}
}
if(!pattern){
pattern = '*.*';
}
if(!options){
options = { matchBase: true };
}
if (typeof folders === 'string') {
folders = [folders];
}
test = new Minimatch(pattern, options);
foldersProcessed = folders.length;
folders.forEach(function(folder){
readDirectoryRecursively(folder, processFiles, folderReadCallback);
});
}
/**
* Test a file path or list of file paths against a minimatch pattern and return only paths that match the pattern.
*
* var Minimatch = require("minimatch").Minimatch,
* pattern = new Minimatch('*.js', { matchBase: true }),
* result;
*
* result = matchPattern(pattern, ['C:/myFile.js', 'CL/myOtherFile.css']); // Will return only the js file.
*
* @method matchPattern
* @param {Minimatch} matchPatten - the pattern a file path must match.
* @param {[] | string} files - file path or array of file path
* @returns {[]} return all the given files that match the pattern
*/
function matchPattern(matchPatten, files){
var i;
if(typeof files === 'string'){
files = [files];
}
i = files.length;
while(i){
i = i - 1;
if(matchPatten.match(files[i]) === false){
files.splice(i, 1);
}
}
return files;
}
/**
* Read all files in a folder, recursively. Each file gets to be processed by a function to determine if it should
* be included in the final file list result.
*
* @method readDirectoryRecursively
*
* @param {string} folderPath - the full path of the folder.
* @param {function} processFiles - this function should accept a file paths array and return a file paths array.
*
* function processFiles(files){ return files; }
*
* You can manipulate the files array to remove unwanted file for example.
*
* @param {function} callback - once all files are collected, this callback will be invoked with (err, files), where
* 'err' is an error object (or null if all went smoothly) and 'files' is a file paths array (or null, if something
* went wrong);
*
* @private
*/
function readDirectoryRecursively(folderPath, processFiles, callback) {
var results = [],
pending;
function handleFolder(folderPath) {
readDirectoryRecursively(folderPath, processFiles, function recursionCallback(err, files) {
files = processFiles(files);
results = results.concat(files);
pending = pending - 1;
if (!pending) {
callback(null, results);
}
});
}
function handleSingleFile(filePath){
var files = processFiles(filePath);
results = results.concat(files);
pending = pending - 1;
if (!pending){
callback(null, results);
}
}
fs.readdir(folderPath, function(err, list) {
if (err){
return callback(err);
}
pending = list.length;
if (!pending) {
return callback(null, results);
}
list.forEach(function(file) {
file = folderPath + '/' + file;
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
handleFolder(file);
} else {
handleSingleFile(file);
}
});
});
});
}
function readFile(filePath, callback){
fs.readFile(filePath, 'utf8', callback);
}
module.exports = {
getFiles : getFiles,
matchPattern : matchPattern,
readFile : readFile
};
}());