vfile-find-up
Advanced tools
Comparing version 1.0.0 to 2.0.0
325
index.js
@@ -6,5 +6,3 @@ /** | ||
* @module vfile:find-up | ||
* @version 0.0.0 | ||
* @fileoverview Find one or more files by searching the | ||
* file system upwards. | ||
* @fileoverview Find files by searching the file system upwards. | ||
*/ | ||
@@ -14,8 +12,3 @@ | ||
/* eslint-env node */ | ||
/* | ||
* Dependencies. | ||
*/ | ||
/* Dependencies. */ | ||
var fs = require('fs'); | ||
@@ -25,6 +18,13 @@ var path = require('path'); | ||
/* | ||
* Methods. | ||
*/ | ||
/* Constants. */ | ||
var INCLUDE = 1; | ||
var BREAK = 4; | ||
/* Expose. */ | ||
exports.INCLUDE = INCLUDE; | ||
exports.BREAK = BREAK; | ||
exports.one = findOne; | ||
exports.all = findAll; | ||
/* Methods. */ | ||
var readdir = fs.readdir; | ||
@@ -35,228 +35,173 @@ var resolve = path.resolve; | ||
/* | ||
* Constants. | ||
*/ | ||
var DOT = '.'; | ||
var INCLUDE = 1; | ||
var BREAK = 4; | ||
/** | ||
* Check a mask. | ||
* Find a file or a directory upwards. | ||
* | ||
* @param {number} value - Config. | ||
* @param {number} bitmask - Mask. | ||
* @return {boolean} - Whether `mask` matches `config`. | ||
* @param {Function} test - Filter function. | ||
* @param {string?} [cwd] - Path to search from. | ||
* @param {Function} callback - Invoked with a result. | ||
*/ | ||
function mask(value, bitmask) { | ||
return (value & bitmask) === bitmask; | ||
function findOne(test, cwd, callback) { | ||
return find(test, cwd, callback, true); | ||
} | ||
/** | ||
* Wrap a string given as a test. | ||
* Find files or directories upwards. | ||
* | ||
* A normal string checks for equality to both the filename | ||
* and extension. A string starting with a `.` checks for | ||
* that equality too, and also to just the extension. | ||
* | ||
* @param {string} filePath - File-name and file-extension | ||
* joined by a `.`, or file-extension. | ||
* @return {Function} | ||
* @param {Function} test - Filter function. | ||
* @param {string?} [cwd] - Directory to search from. | ||
* @param {Function} callback - Invoked with results. | ||
*/ | ||
function filePathFactory(filePath) { | ||
var isExtensionLike = filePath.charAt(0) === DOT; | ||
var extension = isExtensionLike && filePath.slice(1); | ||
/** | ||
* Check whether the given `file` matches the bound | ||
* value. | ||
* | ||
* @param {VFile} file - Virtual file. | ||
* @return {boolean} - Whether or not there is a match. | ||
*/ | ||
return function (file) { | ||
var name = file.filename + (file.extension ? DOT + file.extension : ''); | ||
return filePath === name || | ||
(isExtensionLike && extension === file.extension); | ||
} | ||
function findAll(test, cwd, callback) { | ||
return find(test, cwd, callback); | ||
} | ||
/** | ||
* Augment `test` from several supported values to a | ||
* function returning a boolean. | ||
* Find applicable files. | ||
* | ||
* @param {string|Function|Array.<string|Function>} test | ||
* - Augmented test. | ||
* @return {Function} - test | ||
* @param {*} test - Filter. | ||
* @param {string?} cwd - Path to search from. | ||
* @param {Function} callback - Invoked with results. | ||
* @param {boolean?} [one] - When `true`, returns the | ||
* first result (`string`), otherwise, returns an array | ||
* of strings. | ||
*/ | ||
function augment(test) { | ||
var index; | ||
var length; | ||
var tests; | ||
function find(test, cwd, callback, one) { | ||
var results = []; | ||
var current; | ||
if (typeof test === 'string') { | ||
return filePathFactory(test); | ||
} | ||
test = augment(test); | ||
if (typeof test === 'function') { | ||
return test; | ||
} | ||
if (!callback) { | ||
callback = cwd; | ||
cwd = null; | ||
} | ||
length = test.length; | ||
index = -1; | ||
tests = []; | ||
current = cwd ? resolve(cwd) : process.cwd(); | ||
while (++index < length) { | ||
tests[index] = augment(test[index]); | ||
} | ||
once(); | ||
return function (file) { | ||
index = -1; | ||
return; | ||
while (++index < length) { | ||
if (tests[index](file)) { | ||
return true; | ||
} | ||
} | ||
/** | ||
* Test a file and check what should be done with | ||
* the resulting file. | ||
* | ||
* @param {string} filePath - Path to file. | ||
* @return {boolean} - `true` when `callback` is | ||
* invoked and iteration should stop. | ||
*/ | ||
function handle(filePath) { | ||
var file = toVFile(filePath); | ||
var result = test(file); | ||
return false; | ||
if (mask(result, INCLUDE)) { | ||
if (one) { | ||
callback(null, file); | ||
return true; | ||
} | ||
results.push(file); | ||
} | ||
} | ||
/** | ||
* Find files and directories upwards. | ||
* | ||
* @example | ||
* find('package.json', '.', console.log); | ||
* | ||
* @private | ||
* @param {Function} test - Filter function. | ||
* @param {string?} directory - Path to directory to search. | ||
* @param {Function} callback - Invoked with results. | ||
* @param {boolean?} [one] - When `true`, returns the | ||
* first result (`string`), otherwise, returns an array | ||
* of strings. | ||
*/ | ||
function find(test, directory, callback, one) { | ||
var results = []; | ||
var currentDirectory; | ||
if (mask(result, BREAK)) { | ||
callback(null, one ? null : results); | ||
return true; | ||
} | ||
} | ||
test = augment(test); | ||
if (!callback) { | ||
callback = directory; | ||
directory = null; | ||
/** Check one directory. */ | ||
function once(child) { | ||
if (handle(current) === true) { | ||
return; | ||
} | ||
currentDirectory = directory ? resolve(directory) : process.cwd(); | ||
readdir(current, function (err, entries) { | ||
var length = entries ? entries.length : 0; | ||
var index = -1; | ||
var entry; | ||
/** | ||
* Test a file-path and check what should be done with | ||
* the resulting file. | ||
* Returns true when iteration should stop. | ||
* | ||
* @param {string} filePath - Path to file. | ||
* @return {boolean} - `true` when `callback` is | ||
* invoked and iteration should stop. | ||
*/ | ||
function handle(filePath) { | ||
var file = toVFile(filePath); | ||
var result = test(file); | ||
if (err) { | ||
entries = []; | ||
} | ||
if (mask(result, INCLUDE)) { | ||
if (one) { | ||
callback(null, file); | ||
return true; | ||
} | ||
while (++index < length) { | ||
entry = entries[index]; | ||
results.push(file); | ||
if (entry !== child && handle(resolve(current, entry)) === true) { | ||
return; | ||
} | ||
} | ||
if (mask(result, BREAK)) { | ||
callback(null, one ? null : results); | ||
return true; | ||
} | ||
} | ||
child = current; | ||
current = dirname(current); | ||
/** TODO */ | ||
function once(childDirectory) { | ||
if (handle(currentDirectory) === true) { | ||
return; | ||
} | ||
if (current === child) { | ||
callback(null, one ? null : results); | ||
return; | ||
} | ||
readdir(currentDirectory, function (err, entries) { | ||
var length = entries ? entries.length : 0; | ||
var index = -1; | ||
var entry; | ||
once(basename(child)); | ||
}); | ||
} | ||
} | ||
if (err) { | ||
entries = []; | ||
} | ||
/** Augment `test` */ | ||
function augment(test) { | ||
if (typeof test === 'function') { | ||
return test; | ||
} | ||
while (++index < length) { | ||
entry = entries[index]; | ||
return typeof test === 'string' ? testString(test) : multiple(test); | ||
} | ||
if (entry !== childDirectory) { | ||
if (handle(resolve(currentDirectory, entry)) === true) { | ||
return; | ||
} | ||
} | ||
} | ||
/** Check multiple tests. */ | ||
function multiple(test) { | ||
var length = test.length; | ||
var index = -1; | ||
var tests = []; | ||
childDirectory = currentDirectory; | ||
currentDirectory = dirname(currentDirectory); | ||
while (++index < length) { | ||
tests[index] = augment(test[index]); | ||
} | ||
if (currentDirectory === childDirectory) { | ||
callback(null, one ? null : results); | ||
return; | ||
} | ||
return check; | ||
once(basename(childDirectory)); | ||
}); | ||
function check(file) { | ||
var result; | ||
index = -1; | ||
while (++index < length) { | ||
result = tests[index](file); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
once(); | ||
return false; | ||
} | ||
} | ||
/** | ||
* Find a file or a directory upwards. | ||
* Wrap a string given as a test. | ||
* | ||
* @example | ||
* findOne('package.json', console.log); | ||
* A normal string checks for equality to both the filename | ||
* and extension. A string starting with a `.` checks for | ||
* that equality too, and also to just the extension. | ||
* | ||
* @param {Function} test - Filter function. | ||
* @param {string?} [directory] - Path to directory to search. | ||
* @param {Function} callback - Invoked with a result. | ||
* @param {string} test - Basename or extname. | ||
* @return {Function} - File-path test. | ||
*/ | ||
function findOne(test, directory, callback) { | ||
return find(test, directory, callback, true); | ||
function testString(test) { | ||
return check; | ||
function check(file) { | ||
return test === file.basename || test === file.extname; | ||
} | ||
} | ||
/** | ||
* Find files or directories upwards. | ||
* | ||
* @example | ||
* findAll('package.json', console.log); | ||
* | ||
* @param {Function} test - Filter function. | ||
* @param {string?} [directory] - Path to directory to search. | ||
* @param {Function} callback - Invoked with results. | ||
*/ | ||
function findAll(test, directory, callback) { | ||
return find(test, directory, callback); | ||
/** Check a mask. */ | ||
function mask(value, bitmask) { | ||
return (value & bitmask) === bitmask; | ||
} | ||
/* | ||
* Expose. | ||
*/ | ||
var findUp = {}; | ||
findUp.INCLUDE = INCLUDE; | ||
findUp.BREAK = BREAK; | ||
findUp.one = findOne; | ||
findUp.all = findAll; | ||
module.exports = findUp; |
{ | ||
"name": "vfile-find-up", | ||
"version": "1.0.0", | ||
"description": "Find one or more files by searching the file system upwards", | ||
"version": "2.0.0", | ||
"description": "Find files by searching the file system upwards", | ||
"license": "MIT", | ||
@@ -11,40 +11,58 @@ "keywords": [ | ||
"up", | ||
"upward", | ||
"upwards", | ||
"above", | ||
"retext", | ||
"mdast" | ||
"upward" | ||
], | ||
"repository": "wooorm/vfile-find-up", | ||
"dependencies": { | ||
"to-vfile": "^1.0.0" | ||
"to-vfile": "^2.0.0" | ||
}, | ||
"author": "Titus Wormer <tituswormer@gmail.com>", | ||
"files": [ | ||
"index.js" | ||
], | ||
"repository": "https://github.com/wooorm/vfile-find-up", | ||
"bugs": "https://github.com/wooorm/vfile-find-up/issues", | ||
"author": "Titus Wormer <tituswormer@gmail.com> (http://wooorm.com)", | ||
"contributors": [ | ||
"Titus Wormer <tituswormer@gmail.com> (http://wooorm.com)" | ||
], | ||
"devDependencies": { | ||
"eslint": "^1.0.0", | ||
"esmangle": "^1.0.0", | ||
"istanbul": "^0.3.0", | ||
"jscs": "^2.0.0", | ||
"jscs-jsdoc": "^1.0.0", | ||
"mdast": "^1.0.0", | ||
"mdast-comment-config": "^1.0.0", | ||
"mdast-github": "^1.0.0", | ||
"mdast-lint": "^1.0.0", | ||
"mdast-slug": "^2.0.0", | ||
"mdast-validate-links": "^1.1.1", | ||
"tape": "^4.2.0" | ||
"nyc": "^8.1.0", | ||
"remark-cli": "^1.0.0", | ||
"remark-comment-config": "^4.0.0", | ||
"remark-github": "^5.0.0", | ||
"remark-lint": "^4.0.0", | ||
"remark-validate-links": "^4.0.0", | ||
"tape": "^4.0.0", | ||
"xo": "^0.16.0" | ||
}, | ||
"scripts": { | ||
"build-md": "mdast . --quiet --frail", | ||
"build-md": "remark . --quiet --frail", | ||
"build": "npm run build-md", | ||
"lint-api": "eslint .", | ||
"lint-style": "jscs --reporter inline .", | ||
"lint": "npm run lint-api && npm run lint-style", | ||
"test-api": "node test/index.js", | ||
"test-coverage": "istanbul cover test/index.js", | ||
"lint": "xo", | ||
"test-api": "node test", | ||
"test-coverage": "nyc --reporter lcov tape test/index.js", | ||
"test": "npm run build && npm run lint && npm run test-coverage" | ||
}, | ||
"nyc": { | ||
"check-coverage": true, | ||
"lines": 100, | ||
"functions": 100, | ||
"branches": 100 | ||
}, | ||
"xo": { | ||
"space": true | ||
}, | ||
"remarkConfig": { | ||
"output": true, | ||
"plugins": { | ||
"comment-config": null, | ||
"github": null, | ||
"lint": { | ||
"list-item-spacing": false, | ||
"heading-increment": false | ||
}, | ||
"validate-links": null | ||
}, | ||
"settings": { | ||
"bullet": "*" | ||
} | ||
} | ||
} |
218
readme.md
@@ -1,9 +0,8 @@ | ||
# vfile-find-up [![Build Status](https://img.shields.io/travis/wooorm/vfile-find-up.svg)](https://travis-ci.org/wooorm/vfile-find-up) [![Coverage Status](https://img.shields.io/codecov/c/github/wooorm/vfile-find-up.svg)](https://codecov.io/github/wooorm/vfile-find-up) | ||
# vfile-find-up [![Build Status][travis-badge]][travis] [![Coverage Status][codecov-badge]][codecov] | ||
Find one or more files (exposed as [VFile](https://github.com/wooorm/vfile)s) | ||
by searching the file system upwards. | ||
Find [vfile][]s by searching the file system upwards. | ||
## Installation | ||
[npm](https://docs.npmjs.com/cli/install): | ||
[npm][npm-install]: | ||
@@ -16,3 +15,3 @@ ```bash | ||
Require dependencies: | ||
Dependencies: | ||
@@ -28,195 +27,92 @@ ```js | ||
findUp.all('package.json', console.log); | ||
/* null [ VFile { | ||
* contents: '', | ||
* messages: [], | ||
* history: [ '/Users/foo/bar/baz/package.json' ], | ||
* directory: '/Users/foo/bar/baz', | ||
* filename: 'package', | ||
* extension: 'json' }, | ||
* VFile { | ||
* contents: '', | ||
* messages: [], | ||
* history: [ '/Users/foo/package.json' ], | ||
* directory: '/Users/foo', | ||
* filename: 'package', | ||
* extension: 'json' } ] | ||
*/ | ||
``` | ||
Search for the first file: | ||
Logs: | ||
```js | ||
findUp.one('package.json', console.log); | ||
/* null VFile { | ||
* contents: '', | ||
* messages: [], | ||
* history: [ '/Users/foo/bar/baz/package.json' ], | ||
* directory: '/Users/foo/bar/baz', | ||
* filename: 'package', | ||
* extension: 'json' } | ||
*/ | ||
null [ VFile { | ||
data: {}, | ||
messages: [], | ||
history: [ '/Users/tilde/projects/oss/vfile-find-up/package.json' ], | ||
cwd: '/Users/tilde/projects/oss/vfile-find-up' } ] | ||
``` | ||
### findUp.one(test\[, directory\], [callback](#function-callbackerr-file)) | ||
Search for the first file: | ||
Find a file or a directory upwards. | ||
**Example** | ||
```js | ||
findUp.one('package.json', console.log); | ||
/* null VFile { | ||
* contents: '', | ||
* messages: [], | ||
* history: [ '/Users/foo/bar/baz/package.json' ], | ||
* directory: '/Users/foo/bar/baz', | ||
* filename: 'package', | ||
* extension: 'json' } | ||
*/ | ||
``` | ||
**Signatures** | ||
Logs: | ||
* `findUp.one(filePath[, directory], callback)`; | ||
* `findUp.one(extension[, directory], callback)`; | ||
* `findUp.one(test[, directory], callback)`; | ||
* `findUp.one(tests[, directory], callback)`. | ||
**Parameters** | ||
* `filePath` (`string`) | ||
— Filename (including extension) to search for; | ||
* `extension` (`string`) | ||
— File extension to search for (must start with a `.`); | ||
* `test` ([`Function`](#function-testfile)) | ||
— Function invoked to check whether a virtual file should be included; | ||
* `tests` (`Array.<Function|filePath|extension>`) | ||
— List of tests, any of which should match a given file for it to | ||
be included. | ||
* `directory` (`string`, optional, default: `process.cwd()`) | ||
— Place to start searching from; | ||
* `callback` ([`Function`](#function-callbackerr-file)); | ||
— Function invoked when a matching file or the top of the volume | ||
is reached. | ||
**Notes** | ||
* Virtual Files are not read (their `content` is not populated). | ||
#### function callback(err, file) | ||
Invoked when a matching file or the top of the volume is reached. | ||
**Parameters** | ||
* `err` (`Error`, optional); | ||
* `file` ([`VFile`](https://github.com/wooorm/vfile), optional). | ||
**Notes** | ||
* The `err` parameter is never populated. | ||
### findUp.all(test\[, directory\], [callback](#function-callbackerr-files)) | ||
Find files or directories upwards. | ||
**Example** | ||
```js | ||
findUp.all('package.json', console.log); | ||
/* null [ VFile { | ||
* contents: '', | ||
* messages: [], | ||
* history: [ '/Users/foo/bar/baz/package.json' ], | ||
* directory: '/Users/foo/bar/baz', | ||
* filename: 'package', | ||
* extension: 'json' }, | ||
* VFile { | ||
* contents: '', | ||
* messages: [], | ||
* history: [ '/Users/foo/package.json' ], | ||
* directory: '/Users/foo', | ||
* filename: 'package', | ||
* extension: 'json' } ] | ||
*/ | ||
null VFile { | ||
data: {}, | ||
messages: [], | ||
history: [ '/Users/tilde/projects/oss/vfile-find-up/package.json' ], | ||
cwd: '/Users/tilde/projects/oss/vfile-find-up' } | ||
``` | ||
**Signatures** | ||
## API | ||
* `findUp.all(filePath[, directory], callback)`; | ||
* `findUp.all(extension[, directory], callback)`; | ||
* `findUp.all(test[, directory], callback)`; | ||
* `findUp.all(tests[, directory], callback)`. | ||
### `vfileFindUp.all(tests[, path], callback)` | ||
**Parameters** | ||
Search for `tests` upwards. Invokes callback with either an error | ||
or an array of files passing `tests`. | ||
Note: Virtual Files are not read (their `contents` is not populated). | ||
* `filePath` (`string`) | ||
— Filename (including extension) to search for; | ||
###### Parameters | ||
* `extension` (`string`) | ||
— File extension to search for (must start with a `.`); | ||
* `tests` (`string|Function|Array.<tests>`) | ||
— A test is a [function invoked with a `vfile`][test]. | ||
If an array is passed in, any test must match a given file for it | ||
to be included. | ||
If a `string` is passed in, the `basename` or `extname` of files | ||
must match it for them to be included. | ||
* `path` (`string`, default: `process.cwd()`) | ||
— Place to searching from; | ||
* `callback` (`function cb(err[, files])`); | ||
— Function invoked with all matching files. | ||
* `test` ([`Function`](#function-testfile)) | ||
— Function invoked to check whether a virtual file should be included; | ||
### `vfileFindUp.one(tests[, path], callback)` | ||
* `tests` (`Array.<Function|filePath|extension>`) | ||
— List of tests, any of which should match a given file for it to | ||
be included. | ||
Like `vfileFindUp.all`, but invokes `callback` with the first found | ||
file, or `null`. | ||
* `directory` (`string`, optional, default: `process.cwd()`) | ||
— Place to start searching from; | ||
### `function test(file)` | ||
* `callback` ([`Function`](#function-callbackerr-files)); | ||
— Function invoked when matching files or the top of the volume | ||
is reached. | ||
Check whether a virtual file should be included. Invoked with a | ||
[vfile][]. | ||
**Notes** | ||
###### Returns | ||
* Virtual Files are not read (their `content` is not populated). | ||
* `true` or `vfileFindUp.INCLUDE` — Include the file in the results; | ||
* `vfileFindUp.BREAK` — Stop searching for files; | ||
* anything else is ignored: the file is not included. | ||
#### function callback(err, files) | ||
The different flags can be combined by using the pipe operator: | ||
`vfileFindUp.INCLUDE | vfileFindUp.BREAK`. | ||
Invoked when files or the top of the volume is reached. | ||
## License | ||
**Parameters** | ||
[MIT][license] © [Titus Wormer][author] | ||
* `err` (`Error`, optional); | ||
* `files` ([`Array.<VFile>`](https://github.com/wooorm/vfile), optional). | ||
<!-- Definitions --> | ||
**Notes** | ||
[travis-badge]: https://img.shields.io/travis/wooorm/vfile-find-up.svg | ||
* The `err` parameter is never populated. | ||
[travis]: https://travis-ci.org/wooorm/vfile-find-up | ||
### function test(file) | ||
[codecov-badge]: https://img.shields.io/codecov/c/github/wooorm/vfile-find-up.svg | ||
Check whether a virtual file should be included. | ||
[codecov]: https://codecov.io/github/wooorm/vfile-find-up | ||
**Parameters** | ||
[npm-install]: https://docs.npmjs.com/cli/install | ||
* `file` ([`VFile`](https://github.com/wooorm/vfile)). | ||
[license]: LICENSE | ||
**Returns**: | ||
[author]: http://wooorm.com | ||
* `boolean` — When truthy, the file is included; | ||
[vfile]: https://github.com/wooorm/vfile | ||
* `number` — Bitmask ([`findUp.INCLUDE`](#findupinclude) and | ||
[`findUp.EXIT`](#findupexit)) to control searching behavior. | ||
### findUp.INCLUDE | ||
Flag used as an alternative to returning `true` from | ||
[`test`](#function-testfile), ensuring the tested file | ||
is included and passed to `callback`. | ||
### findUp.EXIT | ||
Flag used to stop searching for files returned to [`test`](#function-testfile). | ||
## License | ||
[MIT](LICENSE) © [Titus Wormer](http://wooorm.com) | ||
[test]: #function-testfile |
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
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
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
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
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
8
9408
4
165
117
1
+ Addedis-buffer@1.1.6(transitive)
+ Addedreplace-ext@1.0.0(transitive)
+ Addedto-vfile@2.2.0(transitive)
+ Addedunist-util-stringify-position@1.1.2(transitive)
+ Addedvfile@2.3.0(transitive)
+ Addedvfile-message@1.1.1(transitive)
+ Addedx-is-function@1.0.4(transitive)
- Removedto-vfile@1.0.0(transitive)
- Removedvfile@1.4.0(transitive)
Updatedto-vfile@^2.0.0