test-exclude
Advanced tools
Comparing version 5.1.0 to 5.2.0
@@ -6,2 +6,14 @@ # Change Log | ||
# [5.2.0](https://github.com/istanbuljs/istanbuljs/compare/test-exclude@5.1.0...test-exclude@5.2.0) (2019-03-12) | ||
### Features | ||
* Add TestExclude.globSync to find all files ([#309](https://github.com/istanbuljs/istanbuljs/issues/309)) ([2d7ea72](https://github.com/istanbuljs/istanbuljs/commit/2d7ea72)) | ||
* Support turning of node_modules default exclude via flag ([#213](https://github.com/istanbuljs/istanbuljs/issues/213)) ([9b4b34c](https://github.com/istanbuljs/istanbuljs/commit/9b4b34c)) | ||
# [5.1.0](https://github.com/istanbuljs/istanbuljs/compare/test-exclude@5.0.1...test-exclude@5.1.0) (2019-01-26) | ||
@@ -8,0 +20,0 @@ |
229
index.js
@@ -0,120 +1,148 @@ | ||
const path = require('path'); | ||
const arrify = require('arrify'); | ||
const glob = require('glob'); | ||
const minimatch = require('minimatch'); | ||
const path = require('path'); | ||
const readPkgUp = require('read-pkg-up'); | ||
const requireMainFilename = require('require-main-filename'); | ||
function TestExclude(opts) { | ||
Object.assign( | ||
this, | ||
{ | ||
cwd: process.cwd(), | ||
include: false, | ||
relativePath: true, | ||
configKey: null, // the key to load config from in package.json. | ||
configPath: null, // optionally override requireMainFilename. | ||
configFound: false | ||
}, | ||
opts | ||
); | ||
class TestExclude { | ||
constructor(opts) { | ||
Object.assign( | ||
this, | ||
{ | ||
cwd: process.cwd(), | ||
include: false, | ||
relativePath: true, | ||
configKey: null, // the key to load config from in package.json. | ||
configPath: null, // optionally override requireMainFilename. | ||
configFound: false, | ||
excludeNodeModules: true, | ||
extension: false | ||
}, | ||
opts | ||
); | ||
if (typeof this.include === 'string') this.include = [this.include]; | ||
if (typeof this.exclude === 'string') this.exclude = [this.exclude]; | ||
if (typeof this.include === 'string') { | ||
this.include = [this.include]; | ||
} | ||
if (!this.include && !this.exclude && this.configKey) { | ||
Object.assign(this, this.pkgConf(this.configKey, this.configPath)); | ||
} | ||
if (typeof this.exclude === 'string') { | ||
this.exclude = [this.exclude]; | ||
} | ||
if (!this.exclude || !Array.isArray(this.exclude)) { | ||
this.exclude = exportFunc.defaultExclude; | ||
} | ||
if (typeof this.extension === 'string') { | ||
this.extension = [this.extension]; | ||
} else if ( | ||
!Array.isArray(this.extension) || | ||
this.extension.length === 0 | ||
) { | ||
this.extension = false; | ||
} | ||
if (this.include && this.include.length > 0) { | ||
this.include = prepGlobPatterns(arrify(this.include)); | ||
} else { | ||
this.include = false; | ||
} | ||
if (!this.include && !this.exclude && this.configKey) { | ||
Object.assign(this, this.pkgConf(this.configKey, this.configPath)); | ||
} | ||
if (this.exclude.indexOf('**/node_modules/**') === -1) { | ||
this.exclude.push('**/node_modules/**'); | ||
if (!this.exclude || !Array.isArray(this.exclude)) { | ||
this.exclude = exportFunc.defaultExclude; | ||
} | ||
if (this.include && this.include.length > 0) { | ||
this.include = prepGlobPatterns(arrify(this.include)); | ||
} else { | ||
this.include = false; | ||
} | ||
if ( | ||
this.excludeNodeModules && | ||
!this.exclude.includes('**/node_modules/**') | ||
) { | ||
this.exclude.push('**/node_modules/**'); | ||
} | ||
this.exclude = prepGlobPatterns([].concat(arrify(this.exclude))); | ||
this.handleNegation(); | ||
} | ||
this.exclude = prepGlobPatterns([].concat(arrify(this.exclude))); | ||
/* handle the special case of negative globs | ||
* (!**foo/bar); we create a new this.excludeNegated set | ||
* of rules, which is applied after excludes and we | ||
* move excluded include rules into this.excludes. | ||
*/ | ||
handleNegation() { | ||
const noNeg = e => e.charAt(0) !== '!'; | ||
const onlyNeg = e => e.charAt(0) === '!'; | ||
const stripNeg = e => e.slice(1); | ||
this.handleNegation(); | ||
} | ||
if (Array.isArray(this.include)) { | ||
const includeNegated = this.include.filter(onlyNeg).map(stripNeg); | ||
this.exclude.push(...prepGlobPatterns(includeNegated)); | ||
this.include = this.include.filter(noNeg); | ||
} | ||
// handle the special case of negative globs | ||
// (!**foo/bar); we create a new this.excludeNegated set | ||
// of rules, which is applied after excludes and we | ||
// move excluded include rules into this.excludes. | ||
TestExclude.prototype.handleNegation = function() { | ||
if (Array.isArray(this.include)) { | ||
const includeNegated = this.include | ||
.filter(function(e) { | ||
return e.charAt(0) === '!'; | ||
}) | ||
.map(function(e) { | ||
return e.slice(1); | ||
}); | ||
this.exclude.push.apply(this.exclude, prepGlobPatterns(includeNegated)); | ||
this.include = this.include.filter(function(e) { | ||
return e.charAt(0) !== '!'; | ||
}); | ||
this.excludeNegated = this.exclude.filter(onlyNeg).map(stripNeg); | ||
this.exclude = this.exclude.filter(noNeg); | ||
this.excludeNegated = prepGlobPatterns(this.excludeNegated); | ||
} | ||
this.excludeNegated = this.exclude | ||
.filter(function(e) { | ||
return e.charAt(0) === '!'; | ||
}) | ||
.map(function(e) { | ||
return e.slice(1); | ||
}); | ||
this.exclude = this.exclude.filter(function(e) { | ||
return e.charAt(0) !== '!'; | ||
}); | ||
this.excludeNegated = prepGlobPatterns(this.excludeNegated); | ||
}; | ||
shouldInstrument(filename, relFile) { | ||
if ( | ||
this.extension && | ||
!this.extension.some(ext => filename.endsWith(ext)) | ||
) { | ||
return false; | ||
} | ||
TestExclude.prototype.shouldInstrument = function(filename, relFile) { | ||
var pathToCheck = filename; | ||
let pathToCheck = filename; | ||
if (this.relativePath) { | ||
relFile = relFile || path.relative(this.cwd, filename); | ||
if (this.relativePath) { | ||
relFile = relFile || path.relative(this.cwd, filename); | ||
// Don't instrument files that are outside of the current working directory. | ||
if (/^\.\./.test(path.relative(this.cwd, filename))) return false; | ||
// Don't instrument files that are outside of the current working directory. | ||
if (/^\.\./.test(path.relative(this.cwd, filename))) { | ||
return false; | ||
} | ||
pathToCheck = relFile.replace(/^\.[\\/]/, ''); // remove leading './' or '.\'. | ||
pathToCheck = relFile.replace(/^\.[\\/]/, ''); // remove leading './' or '.\'. | ||
} | ||
const dot = { dot: true }; | ||
const matches = pattern => minimatch(pathToCheck, pattern, dot); | ||
return ( | ||
(!this.include || this.include.some(matches)) && | ||
(!this.exclude.some(matches) || this.excludeNegated.some(matches)) | ||
); | ||
} | ||
return ( | ||
(!this.include || | ||
this.include.some(include => | ||
minimatch(pathToCheck, include, { dot: true }) | ||
)) && | ||
(!this.exclude.some(exclude => | ||
minimatch(pathToCheck, exclude, { dot: true }) | ||
) || | ||
this.excludeNegated.some(exclude => | ||
minimatch(pathToCheck, exclude, { dot: true }) | ||
)) | ||
); | ||
}; | ||
pkgConf(key, path) { | ||
const cwd = path || requireMainFilename(require); | ||
const obj = readPkgUp.sync({ cwd }); | ||
TestExclude.prototype.pkgConf = function(key, path) { | ||
const obj = readPkgUp.sync({ | ||
cwd: path || requireMainFilename(require) | ||
}); | ||
if (obj.pkg && obj.pkg[key] && typeof obj.pkg[key] === 'object') { | ||
this.configFound = true; | ||
if (obj.pkg && obj.pkg[key] && typeof obj.pkg[key] === 'object') { | ||
this.configFound = true; | ||
return obj.pkg[key]; | ||
} else { | ||
return obj.pkg[key]; | ||
} | ||
return {}; | ||
} | ||
}; | ||
globSync(cwd = this.cwd) { | ||
const globPatterns = getExtensionPattern(this.extension || []); | ||
const globOptions = { cwd, nodir: true, dot: true }; | ||
/* If we don't have any excludeNegated then we can optimize glob by telling | ||
* it to not iterate into unwanted directory trees (like node_modules). */ | ||
if (this.excludeNegated.length === 0) { | ||
globOptions.ignore = this.exclude; | ||
} | ||
return glob | ||
.sync(globPatterns, globOptions) | ||
.filter(file => this.shouldInstrument(path.resolve(cwd, file))); | ||
} | ||
} | ||
function prepGlobPatterns(patterns) { | ||
return patterns.reduce(function(result, pattern) { | ||
return patterns.reduce((result, pattern) => { | ||
// Allow gitignore style of directory exclusion | ||
@@ -134,6 +162,17 @@ if (!/\/\*\*$/.test(pattern)) { | ||
var exportFunc = function(opts) { | ||
return new TestExclude(opts); | ||
}; | ||
function getExtensionPattern(extension) { | ||
switch (extension.length) { | ||
case 0: | ||
return '**'; | ||
case 1: | ||
return `**/*${extension[0]}`; | ||
default: | ||
return `**/*{${extension.join()}}`; | ||
} | ||
} | ||
const exportFunc = opts => new TestExclude(opts); | ||
const devConfigs = ['ava', 'babel', 'jest', 'nyc', 'rollup', 'webpack']; | ||
exportFunc.defaultExclude = [ | ||
@@ -147,5 +186,5 @@ 'coverage/**', | ||
'**/node_modules/**', | ||
'**/babel.config.js' | ||
`**/{${devConfigs.join()}}.config.js` | ||
]; | ||
module.exports = exportFunc; |
{ | ||
"name": "test-exclude", | ||
"version": "5.1.0", | ||
"version": "5.2.0", | ||
"description": "test for inclusion or exclusion of paths using pkg-conf and globs", | ||
@@ -28,8 +28,9 @@ "main": "index.js", | ||
}, | ||
"homepage": "https://github.com/istanbuljs/istanbuljs#readme", | ||
"homepage": "https://istanbul.js.org/", | ||
"dependencies": { | ||
"arrify": "^1.0.1", | ||
"glob": "^7.1.3", | ||
"minimatch": "^3.0.4", | ||
"read-pkg-up": "^4.0.0", | ||
"require-main-filename": "^1.0.1" | ||
"require-main-filename": "^2.0.0" | ||
}, | ||
@@ -39,3 +40,3 @@ "engines": { | ||
}, | ||
"gitHead": "7875defdc3c3640787ac5d83700246de119e8b83" | ||
"gitHead": "c81b051d83217947dfd97d8d06532bd5013e98c3" | ||
} |
17126
155
5
+ Addedglob@^7.1.3
+ Addedfs.realpath@1.0.0(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedrequire-main-filename@2.0.0(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removedrequire-main-filename@1.0.1(transitive)
Updatedrequire-main-filename@^2.0.0