bower-files
Advanced tools
Comparing version
@@ -5,31 +5,45 @@ 'use strict'; | ||
var util = require('util'); | ||
var path = require('path'); | ||
var BowerConfig = require('bower-config'); | ||
var assign = require('object-assign'); | ||
var isAbsolute = require('is-absolute'); | ||
var json = require('read-json-sync'); | ||
var untildify = require('untildify'); | ||
var MainComponent = require('./main-component'); | ||
var FileFilter = require('./file-filter'); | ||
var assert = require('assert'); | ||
var path = require('path'); | ||
var util = require('util'); | ||
var BowerConfig = require('bower-config'); | ||
var isAbsolute = require('is-absolute'); | ||
var assign = require('object-assign'); | ||
var untildify = require('untildify'); | ||
var Component = require('./component'); | ||
var FileFilter = require('./file-filter'); | ||
/** | ||
* @class BowerFiles | ||
*/ | ||
function BowerFiles(options) { | ||
if (!(this instanceof BowerFiles)) { return new BowerFiles(options); } | ||
// Initialize the normalize the configuration | ||
this._initConfig(options); | ||
options = normalizeOptions(options); | ||
// Get the main bower file | ||
this._component = new MainComponent({ | ||
json: json(this._config.json), | ||
dir: path.dirname(this._config.json), | ||
componentsDir: this._config.dir, | ||
overrides: this._config.overrides, | ||
componentJson: this._config.componentJson | ||
this.component = new Component({ | ||
dir: options.cwd, | ||
dependencyDir: options.dir, | ||
json: options.json, | ||
componentJson: options.componentJson, | ||
overrides: options.overrides, | ||
isRoot: true | ||
}); | ||
// Inheric from FileFilter | ||
this.cwd = options.cwd; | ||
// TODO deprectate | ||
this._fileFilterConfig = { | ||
camelCase: options.camelCase | ||
}; | ||
Object.defineProperties(this, { | ||
_config: { | ||
get: util.deprecate(function () { | ||
return options; | ||
}, 'bowerFiles._config: Access to _config is deprecated') | ||
}, | ||
_component: { | ||
get: util.deprecate(function () { | ||
return this.component; | ||
}.bind(this), 'bowerFiles._component: Access to _component is deprecated') | ||
} | ||
}); | ||
FileFilter.call(this); | ||
@@ -39,27 +53,19 @@ } | ||
/** | ||
* @name {Array|Object} BowerFiles.old | ||
* @description A method to conform to the 2.x version of this module. | ||
*/ | ||
BowerFiles.old = function (options) { | ||
options = options || {}; | ||
BowerFiles.old = util.deprecate(function (options) { | ||
options = assign({ext: true, join: {}}, options); | ||
var lib = new BowerFiles(options) | ||
return new BowerFiles(options) | ||
.self(Boolean(options.self)) | ||
.dev(Boolean(options.dev)) | ||
.dev(Boolean(options.dev)) | ||
.ext(options.ext) | ||
.join(options.join); | ||
return lib.files; | ||
}; | ||
.join(options.join) | ||
.files; | ||
}, 'BowerFiles.old: This is an old api. Read the docs on the new api'); | ||
/** | ||
* @name BowerFiles#_initConfig | ||
* @description Initializes the configuration of the BowerFiles instance. | ||
*/ | ||
BowerFiles.prototype._initConfig = function (options) { | ||
// Default options | ||
// We don't pass in dir, because if it isn't passed, we wan the default to | ||
// come from .bowerc | ||
this._config = assign({ | ||
function normalizeOptions(options) { | ||
if (options && typeof options.camelCase !== 'undefined') { | ||
console.log('bowerFiles.options.camelCase: Use .camelCase(true).'); | ||
} | ||
options = assign({ | ||
cwd: process.cwd(), | ||
@@ -69,25 +75,21 @@ json: 'bower.json', | ||
componentJson: '.bower.json', | ||
camelCase: true | ||
camelCase: true, | ||
dir: null | ||
}, options); | ||
// check if this._config.cwd is absolute | ||
if (!isAbsolute(this._config.cwd)) { | ||
throw new Error('options.cwd must be an absolute path'); | ||
} | ||
assert( | ||
isAbsolute(options.cwd || ''), | ||
'options.cwd must be an absolute path' | ||
); | ||
// If a dir option wasn't given, lets read the bowerrc files | ||
// @see https://github.com/bower/config | ||
if (!this._config.dir) { | ||
// This gets us the cwd and directory options that we can use. | ||
var bowerrc = new BowerConfig(this._config.cwd).load().toObject(); | ||
// Normalize the cwd and directories given by bowerrc | ||
bowerrc.cwd = untildify(bowerrc.cwd); | ||
bowerrc.directory = untildify(bowerrc.directory); | ||
this._config.dir = path.resolve(bowerrc.cwd, bowerrc.directory); | ||
} else { | ||
this._config.dir = path.resolve(this._config.cwd, this._config.dir); | ||
if (!options.dir) { | ||
var bowerrc = new BowerConfig(options.cwd).load().toObject(); | ||
options.cwd = untildify(bowerrc.cwd); | ||
options.dir = untildify(bowerrc.directory); | ||
} | ||
options.dir = path.resolve(options.cwd, options.dir); | ||
// Make the json option absolute | ||
this._config.json = path.resolve(this._config.cwd, this._config.json); | ||
}; | ||
return options; | ||
} | ||
@@ -5,54 +5,119 @@ 'use strict'; | ||
var path = require('path'); | ||
var assign = require('object-assign'); | ||
var json = require('read-json-sync'); | ||
var camelCase = require('camelcase'); | ||
var isSymlink = require('is-symlink-sync'); | ||
var mainFiles = require('./utils/main-files'); | ||
var getDeps = require('./utils/get-deps'); | ||
var depFiles = require('./utils/dep-files'); | ||
var assert = require('assert'); | ||
var path = require('path'); | ||
var util = require('util'); | ||
var arrify = require('arrify'); | ||
var globby = require('globby'); | ||
var isAbsolute = require('is-absolute'); | ||
var isSymlink = require('is-symlink-sync'); | ||
var assign = require('object-assign'); | ||
var readJson = require('read-json-sync'); | ||
function Component(options) { | ||
if (!(this instanceof Component)) { return new Component(options); } | ||
// options = { | ||
// name: '', | ||
// dir: '' | ||
// } | ||
assign(this, options); | ||
options = normalizeOptions(options); | ||
// Set the path | ||
this.path = path.resolve(this.dir, this.name); | ||
this.json = readJson(path.resolve(options.dir, options.json)); | ||
this.name = options.isRoot // TODO deprecate 'self' name | ||
? 'self' | ||
: this.json.name || path.basename(options.dir); | ||
options.overrides = assign({}, this.json.overrides, options.overrides); | ||
assign(this.json, options.overrides[this.name]); | ||
// Get this bower.json | ||
var bowerFile = isSymlink(this.path) ? 'bower.json' : this.componentJson; | ||
this.json = json(path.resolve(this.path, bowerFile)); | ||
this.files = Component.mainFiles(options.dir, this.json.main); | ||
// Apply the overrides | ||
assign(this.json, this.overrides[this.name]); | ||
if (!this.json.main) { | ||
throw new Error(this.name + ' has no main property'); | ||
this.dependencies = getDependencies(this.json.dependencies, options); | ||
if (options.isRoot) { | ||
this.devDependencies = getDependencies(this.json.devDependencies, options); | ||
} | ||
// Get the main files | ||
this.files = mainFiles(this.json.main, this.path); | ||
Object.defineProperties(this, { | ||
dir: { | ||
get: util.deprecate(function () { | ||
return options.dependencyDir; | ||
}, 'component.dir: access to dir is deprecated') | ||
}, | ||
path: { | ||
get: util.deprecate(function () { | ||
return options.dir; | ||
}, 'component.path: access to path is deprecated') | ||
} | ||
}); | ||
} | ||
// Get the dependencies | ||
this.dependencies = getDeps(this.json.dependencies, { | ||
dir: this.dir, | ||
overrides: this.overrides, | ||
componentJson: this.componentJson | ||
Component.mainFiles = function mainFiles(dir, mainDef) { | ||
return globby.sync(arrify(mainDef), {cwd: dir}).map(function (file) { | ||
return path.resolve(dir, file); | ||
}); | ||
}; | ||
} | ||
Component.prototype = { | ||
getDependencies: function (options) { | ||
options = assign({ | ||
self: false, | ||
dev: false, | ||
main: true | ||
}, options); | ||
Component.prototype.getFiles = function () { | ||
return depFiles(this.dependencies, this.files); | ||
assert( | ||
!options.self || this.json.main, | ||
this.json.name + ' has no main property' | ||
); | ||
var components = []; | ||
if (options.dev) { | ||
components = components.concat(this.devDependencies || []); | ||
} | ||
if (options.main) { | ||
components = components.concat(this.dependencies || []); | ||
} | ||
var dependencies = components | ||
.reduce(function (deps, dep) { | ||
return deps.concat(dep.getDependencies({self: true})); | ||
}, []) | ||
.concat(options.self ? this : []); | ||
var depNames = dependencies.map(function (dep) { return dep.name; }); | ||
return dependencies.filter(function (dep, i) { | ||
return depNames.indexOf(dep.name) === i; | ||
}); | ||
} | ||
}; | ||
Component.prototype.getDeps = function (useCamelCase) { | ||
var hash = {}; | ||
var name = useCamelCase ? camelCase(this.name) : this.name; | ||
hash[name] = this.files; | ||
return assign(hash, depFiles.depHash(this.dependencies)); | ||
}; | ||
function getDependencies(dependencies, options) { | ||
dependencies = dependencies || {}; | ||
return Object.keys(dependencies).map(function (key) { | ||
return new Component(assign({}, options, { | ||
dir: path.resolve(options.dependencyDir, key), | ||
isRoot: false | ||
})); | ||
}); | ||
} | ||
function normalizeOptions(options) { | ||
options = assign({ | ||
dir: null, | ||
dependencyDir: null, | ||
json: 'bower.json', | ||
componentJson: '.bower.json', | ||
overrides: {}, | ||
isRoot: false | ||
}, options); | ||
assert( | ||
isAbsolute(options.dir || ''), | ||
'options.dir must be absolute' | ||
); | ||
assert( | ||
isAbsolute(options.dependencyDir || ''), | ||
'options.dependencyDir must be absolute' | ||
); | ||
options.json = (options.isRoot || isSymlink(options.dir)) | ||
? options.json | ||
: options.componentJson; | ||
return options; | ||
} |
@@ -5,14 +5,9 @@ 'use strict'; | ||
var path = require('path'); | ||
var arrayify = require('arrify'); | ||
var minimatch = require('minimatch'); | ||
var assign = require('object-assign'); | ||
var uniq = require('array-uniq'); | ||
var path = require('path'); | ||
var arrify = require('arrify'); | ||
var camelcase = require('camelcase'); | ||
var minimatch = require('minimatch'); | ||
var assign = require('object-assign'); | ||
var BowerFiles = require('./bower-files'); | ||
/** | ||
* @class FileFilter | ||
* @description A separate class is used in order to be able to use the | ||
* chainable methods without modifying the contents that come out. | ||
*/ | ||
function FileFilter(bowerFiles, options) { | ||
@@ -25,165 +20,126 @@ if (this instanceof BowerFiles) { return; } | ||
join: {}, | ||
camelCase: this.bowerFiles._config.camelCase, | ||
cwd: this.bowerFiles._config.cwd | ||
}, options || {}); | ||
camelCase: true, | ||
cwd: this.bowerFiles.cwd | ||
}, this.bowerFiles._fileFilterConfig, options); | ||
} | ||
var filter = FileFilter.prototype; | ||
/** | ||
* @description Used to the the File Filter out of bowerFiles | ||
*/ | ||
filter._filter = function () { | ||
if (this instanceof BowerFiles) { | ||
FileFilter.prototype = { | ||
_filter: function getFilterInstance() { | ||
if (this instanceof BowerFiles) { | ||
return new FileFilter(this); | ||
} else { | ||
return new FileFilter(this.bowerFiles, this.options); | ||
} | ||
}; | ||
/** | ||
* @function FileFilter.include | ||
* TODO implement FileFilter.include | ||
*/ | ||
// filter.include = function () { | ||
// var self = this._filter(); | ||
// | ||
// return self; | ||
// }; | ||
// filter.get = filter.include; | ||
/** | ||
* @function FileFilter.exlude | ||
* TODO implement FileFilter.exclude | ||
*/ | ||
// filter.exlude = function () { | ||
// var self = this._filter(); | ||
// | ||
// return self; | ||
// }; | ||
/** | ||
* @function FileFilter.join | ||
*/ | ||
filter.join = function (joinDef) { | ||
var self = this._filter(); | ||
assign(self.options.join, joinDef); | ||
return self; | ||
}; | ||
/** | ||
* @function FileFilter.match | ||
*/ | ||
filter.match = function (val) { | ||
var self = this._filter(); | ||
self.options.match = self.options.match.concat(arrayify(val)); | ||
return self; | ||
}; | ||
/** | ||
* @function FileFilter.ext | ||
*/ | ||
filter.ext = function (val) { | ||
var self = this._filter(); | ||
if (val === false) { return self; } | ||
if (val === true) { | ||
self.options.ext = true; | ||
} else { | ||
self.options.ext = self.options.ext.concat(arrayify(val)); | ||
} | ||
return self; | ||
}; | ||
/** | ||
* @function FileFilter.dev | ||
*/ | ||
filter.dev = boolOption('dev', true); | ||
/** | ||
* @function FileFilter.self | ||
*/ | ||
filter.self = boolOption('self', true); | ||
/** | ||
* @function FileFilter.main | ||
*/ | ||
filter.main = boolOption('main', true); | ||
/** | ||
* @function FileFilter.relative | ||
*/ | ||
filter.relative = function(val) { | ||
} | ||
return new FileFilter(this.bowerFiles, this.options); | ||
}, | ||
_boolOption: function (name, val, defaultVal) { | ||
var self = this._filter(); | ||
self.options.relative = val ? val : process.cwd(); | ||
self.options[name] = typeof val === 'boolean' ? val : defaultVal; | ||
return self; | ||
}; | ||
function boolOption(name, defaultVal) { | ||
return function (val) { | ||
}, | ||
join: function join(joinDef) { | ||
var self = this._filter(); | ||
self.options[name] = typeof val === 'boolean' ? val : defaultVal; | ||
assign(self.options.join, joinDef); | ||
return self; | ||
}; | ||
} | ||
/** | ||
* @function FileFilter.filter | ||
*/ | ||
filter.filter = function (options) { | ||
var self = this._filter(); | ||
options.ext = arrayify(options.ext); | ||
options.match = arrayify(options.match); | ||
assign(self.options, options); | ||
return self.files; | ||
}, | ||
match: function match(val) { | ||
var self = this._filter(); | ||
self.options.match = self.options.match.concat(arrify(val)); | ||
return self; | ||
}, | ||
ext: function ext(val) { | ||
var self = this._filter(); | ||
if (val === false) { return self; } | ||
if (val === true) { | ||
self.options.ext = true; | ||
} else { | ||
self.options.ext = self.options.ext.concat(arrify(val)); | ||
} | ||
return self; | ||
}, | ||
relative: function relative(val) { | ||
var self = this._filter(); | ||
self.options.relative = val ? val : self.options.cwd; | ||
return self; | ||
}, | ||
dev: function dev(val) { | ||
return this._filter()._boolOption('dev', val, true); | ||
}, | ||
self: function self(val) { | ||
return this._filter()._boolOption('self', val, true); | ||
}, | ||
main: function main(val) { | ||
return this._filter()._boolOption('main', val, true); | ||
}, | ||
camelCase: function camelCase(val) { | ||
return this._filter()._boolOption('camelCase', val, true); | ||
}, | ||
filter: function (options) { | ||
var self = this._filter(); | ||
assign(self.options, options); | ||
return self.files; | ||
}, | ||
getDependencies: function () { | ||
var self = this._filter(); | ||
var options = self.options; | ||
return self.bowerFiles.component.getDependencies(clearUndefined({ | ||
self: options.self, | ||
dev: options.dev, | ||
main: options.main | ||
})); | ||
} | ||
}; | ||
Object.defineProperty(filter, 'deps', { | ||
get: function () { | ||
Object.defineProperties(FileFilter.prototype, { | ||
files: {get: function () { | ||
var self = this._filter(); | ||
var deps = self.bowerFiles._component.getDeps(self.options); | ||
return Object.keys(deps).reduce(function (finalDeps, depName) { | ||
var files = deps[depName]; | ||
files = patternMatch(files, self.options.match, self.options.cwd); | ||
files = extensionSplit(files, self.options.ext, self.options.join); | ||
finalDeps[depName] = files; | ||
var files = self.getDependencies().reduce(function (depFiles, component) { | ||
return depFiles.concat(component.files); | ||
}, []); | ||
return processFiles(files, self.options); | ||
}}, | ||
deps: {get: function () { | ||
var self = this._filter(); | ||
var options = self.options; | ||
return self.getDependencies().reduce(function (finalDeps, component) { | ||
var name = options.camelCase ? camelcase(component.name) : component.name; | ||
finalDeps[name] = processFiles(component.files, options); | ||
return finalDeps; | ||
}, {}); | ||
} | ||
}}, | ||
depsArray: {get: function () { | ||
var self = this._filter(); | ||
var options = self.options; | ||
return self.getDependencies().map(function (component) { | ||
return { | ||
name: options.camelCase ? camelcase(component.name) : component.name, | ||
files: processFiles(component.files, options) | ||
}; | ||
}); | ||
}} | ||
}); | ||
Object.defineProperty(filter, 'files', { | ||
get: function () { | ||
var self = this._filter(); | ||
// use dev and self options | ||
var files = uniq(self.bowerFiles._component.getFiles(self.options)); | ||
// use match option | ||
files = patternMatch(files, self.options.match, self.options.cwd); | ||
// Use ext option | ||
// If it's an array and it has a length greater than 1 | ||
files = extensionSplit(files, self.options.ext, self.options.join); | ||
if (self.options.relative) { | ||
files = makeRelative(files, self.options.relative); | ||
} | ||
return files; | ||
function processFiles(files, options) { | ||
files = files | ||
.filter(unique()) | ||
.filter(patternMatch(options.match, options.cwd)); | ||
if (options.relative) { | ||
files = makeRelative(files, options.relative); | ||
} | ||
}); | ||
files = extensionSplit(files, options.ext, options.join); | ||
return files; | ||
} | ||
function makeRelative(files, cwd) { | ||
return files.map(function(file) { | ||
return path.relative(cwd, file); | ||
}); | ||
function unique() { | ||
return function(item, index, array) { | ||
return array.indexOf(item) === index; | ||
}; | ||
} | ||
function patternMatch(files, patterns, cwd) { | ||
files = files.map(function (file) { | ||
return file.replace(cwd + path.sep, ''); | ||
}); | ||
patterns.forEach(function (pattern) { | ||
files = files.filter(minimatch.filter(pattern)); | ||
}); | ||
return files.map(function (file) { | ||
return path.join(cwd, file); | ||
}); | ||
function patternMatch(patterns, cwd) { | ||
if (!patterns.length) { return function (val) { return true; }; } | ||
return function (file) { | ||
file = file.replace(cwd + path.sep, ''); | ||
return arrify(patterns).every(function (pattern) { | ||
return minimatch(file, pattern); | ||
}); | ||
}; | ||
} | ||
@@ -194,7 +150,7 @@ | ||
// Split files up by extension | ||
files = files.reduce(function (files, file) { | ||
files = files.reduce(function (filesObj, file) { | ||
var ext = path.extname(file).substr(1); | ||
files[ext] = files[ext] || []; | ||
files[ext].push(file); | ||
return files; | ||
filesObj[ext] = filesObj[ext] || []; | ||
filesObj[ext].push(file); | ||
return filesObj; | ||
}, {}); | ||
@@ -212,3 +168,3 @@ // Get things from the join option | ||
if (exts.length) { | ||
files = exts.reduce(function (extArray, ext) { | ||
files = arrify(exts).reduce(function (extArray, ext) { | ||
return extArray.concat(files[ext] || []); | ||
@@ -219,1 +175,14 @@ }, []); | ||
} | ||
function makeRelative(files, cwd) { | ||
return files.map(function(file) { | ||
return path.relative(cwd, file); | ||
}); | ||
} | ||
function clearUndefined(obj) { | ||
Object.keys(obj).forEach(function (key) { | ||
if (typeof obj[key] === 'undefined') { delete obj[key]; } | ||
}); | ||
return obj; | ||
} |
{ | ||
"name": "bower-files", | ||
"version": "3.8.0", | ||
"main": "./lib/bower-files", | ||
"version": "3.9.0", | ||
"main": "./index", | ||
"description": "Pulls in dynamic list of filepaths to bower components", | ||
@@ -16,3 +16,3 @@ "files": [ | ||
"jshint": "jshint --reporter node_modules/jshint-stylish lib/**", | ||
"check-cov": "istanbul check-coverage --statements 100 --functions 100 --branches 100 --lines 100", | ||
"check-cov": "istanbul check-coverage --statements 90 --functions 90 --branches 90 --lines 90", | ||
"test": "istanbul cover _mocha", | ||
@@ -45,6 +45,6 @@ "posttest": " npm run check-cov; npm run jshint;", | ||
"dependencies": { | ||
"array-uniq": "^1.0.2", | ||
"arrify": "^1.0.0", | ||
"bower-config": "^0.6.1", | ||
"camelcase": "^1.1.0", | ||
"deprecate": "^0.1.0", | ||
"globby": "^2.1.0", | ||
@@ -51,0 +51,0 @@ "is-absolute": "^0.2.2", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
25396
-4.99%8
-27.27%352
-12.66%1
Infinity%+ Added
+ Added
- Removed