Comparing version 0.7.6 to 0.8.0
150
index.js
'use strict'; | ||
/** | ||
* Module dependencies | ||
*/ | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var utils = require('./utils'); | ||
var lazy = require('lazy-cache')(require); | ||
lazy('matched', 'glob'); | ||
lazy('micromatch', 'mm'); | ||
/** | ||
@@ -26,6 +19,6 @@ * Expose `mapFiles` | ||
* | ||
* @param {String} `patterns` Glob patterns to pass to [globby] | ||
* @param {Object} `opts` Options for globby, or the following: | ||
* @param {String} `patterns` Glob patterns to pass to [matched][] | ||
* @param {Object} `opts` Options for [matched][], or the following: | ||
* @option {Boolean} [opts] `cache` If true, results will be cached in memory so that subsequent lookups for the same cwd and patterns don't repeatedly hit the file system. | ||
* @option {Function} [opts] `glob`: Custom glob function. Default is globby. | ||
* @option {Function} [opts] `glob`: Custom glob function. Default is [matched][]. | ||
* @option {Function} [opts] `read`: Custom read function. Default is `fs.readFileSync` | ||
@@ -37,44 +30,53 @@ * @option {Function} [opts] `name`: Custom name function for renaming object keys. Default is the asename of the file, excluding extension. | ||
function mapFiles(patterns, opts) { | ||
opts = opts || {}; | ||
opts.cwd = opts.cwd ? path.resolve(opts.cwd) : process.cwd(); | ||
var files = without(glob(patterns, opts), opts.ignored || []); | ||
function mapFiles(patterns, options) { | ||
var opts = utils.extend({cwd: process.cwd()}, options); | ||
var files = utils.glob.sync(patterns, opts); | ||
if (opts.cache === true) { | ||
var fn = memo('files', opts.cwd, patterns, reduce); | ||
return fn(files, opts); | ||
} | ||
return reduce(files, opts); | ||
return files.reduce(function(acc, filepath) { | ||
var file = createFile(filepath, opts); | ||
acc[renameKey(file, opts)] = file; | ||
return acc; | ||
}, {}); | ||
} | ||
/** | ||
* Expose results cache. | ||
*/ | ||
function define(file, key, fn) { | ||
var cached; | ||
Object.defineProperty(file, key, { | ||
set: function(val) { | ||
cached = val; | ||
}, | ||
get: function() { | ||
return cached || (cached = fn.call(file, file)); | ||
} | ||
}); | ||
} | ||
var cache = mapFiles.cache = {}; | ||
function createFile(filepath, options) { | ||
filepath = path.resolve(options.cwd, filepath); | ||
var file = new utils.Vinyl({path: filepath, cwd: options.cwd}); | ||
function reduce(files, opts) { | ||
return files.reduce(function(acc, fp) { | ||
fp = path.resolve(opts.cwd, fp); | ||
var key = name(fp, acc, opts); | ||
var str = read(fp, acc, opts); | ||
acc[key] = str; | ||
return acc; | ||
}, {}); | ||
} | ||
define(file, 'contents', function() { | ||
return new Buffer(fs.readFileSync(this.path, 'utf8')); | ||
}); | ||
/** | ||
* Default glob function | ||
*/ | ||
define(file, 'content', function() { | ||
return this.contents.toString(); | ||
}); | ||
function glob(patterns, opts) { | ||
opts = opts || {}; | ||
if (typeof opts.glob === 'function') { | ||
return opts.glob(patterns, opts); | ||
define(file, 'json', function() { | ||
return parseJson(this, options); | ||
}); | ||
define(file, 'fn', function() { | ||
return requireFile(this, options); | ||
}); | ||
if (utils.isObject(options.decorate)) { | ||
for (var key in options.decorate) { | ||
define(file, key, function() { | ||
return options.decorate[key](this, options); | ||
}); | ||
} | ||
} | ||
if (opts.cache === true) { | ||
var fn = memo('glob', opts.cwd, patterns, lazy.glob.sync); | ||
return fn(patterns, opts); | ||
} | ||
return lazy.glob.sync(patterns, opts); | ||
return file; | ||
} | ||
@@ -86,56 +88,30 @@ | ||
function name(fp, acc, opts) { | ||
var fn = opts && (opts.name || opts.renameKey); | ||
if (typeof fn === 'function') { | ||
return fn(fp, acc, opts); | ||
function renameKey(file, options) { | ||
if (typeof options.renameKey === 'string') { | ||
return file[options.renameKey]; | ||
} | ||
var ext = path.extname(fp); | ||
return path.basename(fp, ext); | ||
} | ||
/** | ||
* Default read function | ||
*/ | ||
function read(fp, acc, opts) { | ||
fp = path.resolve(fp); | ||
opts = opts || {}; | ||
if (typeof opts.read === 'function') { | ||
return opts.read(fp, acc, opts); | ||
} | ||
var res = {}; | ||
res.content = fs.readFileSync(fp, 'utf8'); | ||
res.path = fp; | ||
return res; | ||
return typeof options.renameKey === 'function' | ||
? options.renameKey(file, options) | ||
: file.relative; | ||
} | ||
/** | ||
* Files cache. | ||
* Require a javascript file | ||
*/ | ||
function memo(name, cwd, patterns, fn) { | ||
var key = name + ':' + cwd + '/' + patterns; | ||
return function() { | ||
if (cache.hasOwnProperty(key)) { | ||
return cache[key]; | ||
} | ||
return (cache[key] = fn.apply(fn, arguments)); | ||
}; | ||
function requireFile(file) { | ||
return file.extname === '.js' | ||
? require(file.path) | ||
: null; | ||
} | ||
/** | ||
* Returns an array of file paths excluding | ||
* files that match the given glob patterns. | ||
* Parse a JSON file | ||
*/ | ||
function without(files, patterns) { | ||
var len = files.length, res = []; | ||
while (len--) { | ||
var fp = files[len]; | ||
if (lazy.mm.any(fp, patterns)) { | ||
continue; | ||
} | ||
res.push(fp); | ||
} | ||
return res; | ||
function parseJson(file) { | ||
return file.extname === '.json' | ||
? JSON.parse(file.contents.toString()) | ||
: {}; | ||
} |
{ | ||
"name": "map-files", | ||
"description": "Return an object for a glob of files. Pass a `rename` function for the keys, or a `parse` function for the content, allowing it to be used for readable or require-able files.", | ||
"version": "0.7.6", | ||
"version": "0.8.0", | ||
"homepage": "https://github.com/jonschlinkert/map-files", | ||
@@ -13,3 +13,4 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)", | ||
"files": [ | ||
"index.js" | ||
"index.js", | ||
"utils.js" | ||
], | ||
@@ -24,9 +25,11 @@ "main": "index.js", | ||
"dependencies": { | ||
"isobject": "^2.0.0", | ||
"lazy-cache": "^1.0.4", | ||
"matched": "^0.4.1", | ||
"micromatch": "^2.3.8" | ||
"vinyl": "^1.1.1" | ||
}, | ||
"devDependencies": { | ||
"extend-shallow": "^2.0.1", | ||
"gray-matter": "^2.0.2", | ||
"gulp-format-md": "^0.1.8", | ||
"js-yaml": "^3.6.0", | ||
"mocha": "^2.4.5", | ||
@@ -57,9 +60,24 @@ "relative": "^3.0.2", | ||
"list": [ | ||
"export-files", | ||
"file-reader", | ||
"filter-files", | ||
"micromatch", | ||
"export-files" | ||
"micromatch" | ||
] | ||
} | ||
}, | ||
"toc": false, | ||
"layout": "default", | ||
"tasks": [ | ||
"readme" | ||
], | ||
"plugins": [ | ||
"gulp-format-md" | ||
], | ||
"lint": { | ||
"reflinks": true | ||
}, | ||
"reflinks": [ | ||
"verb", | ||
"vinyl" | ||
] | ||
} | ||
} |
134
README.md
@@ -1,7 +0,5 @@ | ||
# map-files [![NPM version](https://img.shields.io/npm/v/map-files.svg?style=flat)](https://www.npmjs.com/package/map-files) [![Build Status](https://img.shields.io/travis/jonschlinkert/map-files.svg?style=flat)](https://travis-ci.org/jonschlinkert/map-files) | ||
# map-files [![NPM version](https://img.shields.io/npm/v/map-files.svg?style=flat)](https://www.npmjs.com/package/map-files) [![NPM downloads](https://img.shields.io/npm/dm/map-files.svg?style=flat)](https://npmjs.org/package/map-files) [![Build Status](https://img.shields.io/travis/jonschlinkert/map-files.svg?style=flat)](https://travis-ci.org/jonschlinkert/map-files) | ||
> Return an object for a glob of files. Pass a `rename` function for the keys, or a `parse` function for the content, allowing it to be used for readable or require-able files. | ||
Return an object for a glob of files. Pass a `rename` function for the keys, or a `parse` function for the content, allowing it to be used for readable or require-able files. | ||
As of v0.5.0, map-files returns absolute file paths by default. You can achieve the same results by using a custom `name` function as in the [examples](#options-name). | ||
## Install | ||
@@ -15,26 +13,29 @@ | ||
**Heads up!** | ||
Breaking changes in v0.8.0. See [the history](#history) for details. | ||
## Usage | ||
```js | ||
var files = require('map-files'); | ||
console.log(files('templates/*.txt')); | ||
var mapFiles = require('map-files'); | ||
console.log(mapFiles('templates/*.txt')); | ||
``` | ||
Returns an object that looks something like: | ||
Returns an object of [vinyl](http://github.com/gulpjs/vinyl) files that looks something like this: | ||
```js | ||
{ a: { content: 'AAA', path: 'templates/a.txt' }, | ||
b: { content: 'BBB', path: 'templates/b.txt' }, | ||
c: { content: 'CCC', path: 'templates/c.txt' }} | ||
{ 'test/fixtures/a.txt': <File "test/fixtures/a.txt" <Buffer 41 41 41>>, | ||
'test/fixtures/b.txt': <File "test/fixtures/b.txt" <Buffer 42 42 42>>, | ||
'test/fixtures/c.txt': <File "test/fixtures/c.txt" <Buffer 43 43 43>> } | ||
``` | ||
### options.cache | ||
## Options | ||
Type: `Boolean` | ||
### options.cwd | ||
Default: `false` | ||
Specify the current working directory | ||
If `true`, results will be cached in memory so that subsequent lookups for the same cwd and patterns don't repeatedly hit the file system. | ||
**Params** | ||
### options.cwd | ||
Type: `String` | ||
@@ -44,3 +45,3 @@ | ||
Specify the current working directory | ||
**Example** | ||
@@ -51,46 +52,67 @@ ```js | ||
### options.name | ||
### options.renameKey | ||
Rename the key of each file object: | ||
**Params** | ||
Type: `Function` | ||
Default: `path.basename(fp, path.extname(fp))` | ||
Default: `file.relative` | ||
Rename the key of each file object: | ||
**Example** | ||
```js | ||
var templates = files('templates/*.txt', { | ||
name: function (filepath) { | ||
return path.basename(filepath); | ||
var files = mapFiles('templates/*.txt', { | ||
renameKey: function (file) { | ||
return file.basename; | ||
} | ||
}); | ||
``` | ||
Returns something like: | ||
```js | ||
{ 'a.txt': { content: 'AAA', path: 'templates/a.txt' }, | ||
'b.txt': { content: 'BBB', path: 'templates/b.txt' }, | ||
'c.txt': { content: 'CCC', path: 'templates/c.txt' }} | ||
{ 'a.txt': <File "test/fixtures/a.txt" <Buffer 41 41 41>>, | ||
'b.txt': <File "test/fixtures/b.txt" <Buffer 42 42 42>>, | ||
'c.txt': <File "test/fixtures/c.txt" <Buffer 43 43 43>> } | ||
``` | ||
### options.read | ||
### options.decorate | ||
> Pass a custom `read` function to change the object returned for each file. | ||
Pass an object of methods to decorate as getters onto each file in the results. | ||
Type: `Function` | ||
```js | ||
var yaml = require('js-yaml'); | ||
Default: `fs.readFileSync()` | ||
The default function reads files and returns a string, but you can do anything | ||
you want with the function, like `require` files: | ||
```js | ||
var helpers = files('helpers/*.js', { | ||
read: function (fp) { | ||
return require(path.resolve(fp)); | ||
var files = mapFiles('test/fixtures/*.yml', { | ||
renameKey: 'stem', | ||
decorate: { | ||
yaml: function(file) { | ||
return yaml.safeLoad(file.contents.toString()); | ||
} | ||
} | ||
}); | ||
//=> { a: [Function: foo], b: [Function: bar], c: [Function: baz] } | ||
console.log(files.a.yaml); | ||
//=> {title: 'AAA'} | ||
``` | ||
## Other files libs | ||
## History | ||
**v0.8.0** | ||
* `options.name` was removed, use `options.renameKey` instead. | ||
* `options.cache` was removed | ||
* `options.read` was removed | ||
* `options.decorate` was added. See the [decorate docs](#options.decorate). | ||
**v0.5.0** | ||
As of v0.5.0, map-files returns absolute file paths by default. You can achieve the same results by using a custom `name` function as in the [examples](#options-name). | ||
## Related projects | ||
You might also be interested in these projects: | ||
* [export-files](https://www.npmjs.com/package/export-files): node.js utility for exporting a directory of files as modules. | [homepage](https://github.com/jonschlinkert/export-files) | ||
@@ -101,3 +123,22 @@ * [file-reader](https://www.npmjs.com/package/file-reader): Read a glob of files, dynamically choosing the reader or requiring the files based on… [more](https://www.npmjs.com/package/file-reader) | [homepage](https://github.com/jonschlinkert/file-reader) | ||
## Contributing | ||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/map-files/issues/new). | ||
## Building docs | ||
Generate readme and API documentation with [verb](https://github.com/verbose/verb): | ||
```sh | ||
$ npm install verb && npm run docs | ||
``` | ||
Or, if [verb](https://github.com/verbose/verb) is installed globally: | ||
```sh | ||
$ verb | ||
``` | ||
## Running tests | ||
Install dev dependencies: | ||
@@ -109,12 +150,11 @@ | ||
## Contributing | ||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/map-files/issues/new). | ||
## Author | ||
## Author | ||
**Jon Schlinkert** | ||
+ [github/jonschlinkert](https://github.com/jonschlinkert) | ||
+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
* [github/jonschlinkert](https://github.com/jonschlinkert) | ||
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) | ||
## License | ||
Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). | ||
@@ -125,4 +165,2 @@ Released under the [MIT license](https://github.com/jonschlinkert/map-files/blob/master/LICENSE). | ||
_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on April 23, 2016._ | ||
[globby]: https://github.com/sindresorhus/globby | ||
_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on April 23, 2016._ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
10414
5
160
4
6
110
4
+ Addedisobject@^2.0.0
+ Addedvinyl@^1.1.1
+ Addedclone@1.0.4(transitive)
+ Addedclone-stats@0.0.1(transitive)
+ Addedreplace-ext@0.0.1(transitive)
+ Addedvinyl@1.2.0(transitive)
- Removedmicromatch@^2.3.8
- Removedarr-diff@2.0.0(transitive)
- Removedarr-flatten@1.1.0(transitive)
- Removedarray-unique@0.2.1(transitive)
- Removedbraces@1.8.5(transitive)
- Removedexpand-brackets@0.1.5(transitive)
- Removedexpand-range@1.8.2(transitive)
- Removedextglob@0.3.2(transitive)
- Removedfilename-regex@2.0.1(transitive)
- Removedfill-range@2.2.4(transitive)
- Removedfor-in@1.0.2(transitive)
- Removedfor-own@0.1.5(transitive)
- Removedglob-base@0.3.0(transitive)
- Removedglob-parent@2.0.0(transitive)
- Removedis-dotfile@1.0.3(transitive)
- Removedis-equal-shallow@0.1.3(transitive)
- Removedis-number@2.1.04.0.0(transitive)
- Removedis-posix-bracket@0.1.1(transitive)
- Removedis-primitive@2.0.0(transitive)
- Removedkind-of@6.0.3(transitive)
- Removedmath-random@1.0.4(transitive)
- Removedmicromatch@2.3.11(transitive)
- Removednormalize-path@2.1.1(transitive)
- Removedobject.omit@2.0.1(transitive)
- Removedparse-glob@3.0.4(transitive)
- Removedpreserve@0.2.0(transitive)
- Removedrandomatic@3.1.1(transitive)
- Removedregex-cache@0.4.4(transitive)
- Removedremove-trailing-separator@1.1.0(transitive)
- Removedrepeat-element@1.1.4(transitive)
- Removedrepeat-string@1.6.1(transitive)