127 lines
2.7 KiB
JavaScript
127 lines
2.7 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import _ from 'lodash';
|
|
import hasIndex from './hasIndex';
|
|
import validateTargetDirectory from './validateTargetDirectory';
|
|
|
|
const hasNoExtension = (fileName) => {
|
|
const matches = fileName.match(/\./g);
|
|
|
|
return !matches;
|
|
};
|
|
|
|
const hasMultipleExtensions = (fileName) => {
|
|
const matches = fileName.match(/\./g);
|
|
|
|
return matches && matches.length > 1;
|
|
};
|
|
|
|
const isSafeName = (fileName) => {
|
|
return /^[_a-z][\w.]*$/i.test(fileName);
|
|
};
|
|
|
|
const stripExtension = (fileName) => {
|
|
const pos = fileName.lastIndexOf('.');
|
|
|
|
if (pos === -1) {
|
|
return fileName;
|
|
}
|
|
|
|
return fileName.slice(0, Math.max(0, pos));
|
|
};
|
|
|
|
const removeDuplicates = (files, preferredExtension) => {
|
|
return _.filter(files, (fileName) => {
|
|
const withoutExtension = stripExtension(fileName);
|
|
const mainAlternative = withoutExtension + '.' + preferredExtension;
|
|
|
|
if (mainAlternative === fileName) {
|
|
return true;
|
|
}
|
|
|
|
return !_.includes(files, mainAlternative);
|
|
});
|
|
};
|
|
|
|
const removeIgnoredFiles = (files, ignorePatterns = []) => {
|
|
if (ignorePatterns.length === 0) {
|
|
return files;
|
|
}
|
|
|
|
const patterns = ignorePatterns.map((pattern) => {
|
|
if (_.startsWith(pattern, '/') && _.endsWith(pattern, '/')) {
|
|
const patternWithoutSlashes = pattern.slice(1, -1);
|
|
|
|
return new RegExp(patternWithoutSlashes);
|
|
}
|
|
|
|
return new RegExp(pattern);
|
|
});
|
|
|
|
return _.filter(files, (fileName) => {
|
|
let pattern;
|
|
|
|
for (pattern of patterns) {
|
|
if (fileName.match(pattern) !== null) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
};
|
|
|
|
export default (directoryPath, options = {}) => {
|
|
if (!validateTargetDirectory(directoryPath, options)) {
|
|
return false;
|
|
}
|
|
|
|
const {
|
|
extensions = ['js'],
|
|
config = {},
|
|
ignoreDirectories = false,
|
|
} = options;
|
|
|
|
let children;
|
|
|
|
children = fs.readdirSync(directoryPath);
|
|
|
|
children = _.filter(children, (fileName) => {
|
|
const absolutePath = path.resolve(directoryPath, fileName);
|
|
const isDirectory = fs.statSync(absolutePath).isDirectory();
|
|
|
|
if (!isSafeName(fileName)) {
|
|
return false;
|
|
}
|
|
|
|
if (hasNoExtension(fileName) && !isDirectory) {
|
|
return false;
|
|
}
|
|
|
|
if (hasMultipleExtensions(fileName)) {
|
|
return false;
|
|
}
|
|
|
|
if (_.startsWith(fileName, options.outputFile || 'index.js')) {
|
|
return false;
|
|
}
|
|
|
|
if (!isDirectory && !extensions.some((extension) => {
|
|
return _.endsWith(fileName, '.' + extension);
|
|
})) {
|
|
return false;
|
|
}
|
|
|
|
if (isDirectory && (!hasIndex(absolutePath, options) || ignoreDirectories)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
children = removeDuplicates(children, extensions[0]);
|
|
children = removeIgnoredFiles(children, config.ignore);
|
|
|
|
return children.sort();
|
|
};
|