vfile-find-up
Advanced tools
Comparing version 5.0.1 to 6.0.0
274
index.js
@@ -1,100 +0,174 @@ | ||
'use strict' | ||
/** | ||
* @typedef {import('vfile').VFile} VFile | ||
* @typedef {string|Assert|Array.<string|Assert>} Test | ||
* @typedef {(file: VFile) => number|boolean|void} Assert | ||
*/ | ||
var fs = require('fs') | ||
var path = require('path') | ||
var toVFile = require('to-vfile') | ||
import fs from 'fs' | ||
import path from 'path' | ||
import {toVFile} from 'to-vfile' | ||
var INCLUDE = 1 | ||
var BREAK = 4 | ||
export const INCLUDE = 1 | ||
export const BREAK = 4 | ||
exports.INCLUDE = INCLUDE | ||
exports.BREAK = BREAK | ||
exports.one = findOne | ||
exports.all = findAll | ||
export const findUp = | ||
/** | ||
* @type {{ | ||
* (test: Test, cwd: string, callback: (error: Error|null, files: Array.<VFile>) => void): void | ||
* (test: Test, callback: (error: Error|null, files: Array.<VFile>) => void): void | ||
* (test: Test, cwd?: string): Promise.<Array.<VFile>> | ||
* }} | ||
*/ | ||
( | ||
/** | ||
* Find a files or directories upwards. | ||
* | ||
* @param {Test} test | ||
* @param {string} cwd | ||
* @param {(error: Error|null, files: Array.<VFile>) => void} callback | ||
* @returns {unknown} | ||
*/ | ||
function (test, cwd, callback) { | ||
return find(test, cwd, callback) | ||
} | ||
) | ||
var readdir = fs.readdir | ||
var resolve = path.resolve | ||
var dirname = path.dirname | ||
var basename = path.basename | ||
export const findUpOne = | ||
/** | ||
* @type {{ | ||
* (test: Test, cwd: string, callback: (error: Error|null, file?: VFile) => void): void | ||
* (test: Test, callback: (error: Error|null, file?: VFile) => void): void | ||
* (test: Test, cwd?: string): Promise.<VFile> | ||
* }} | ||
*/ | ||
( | ||
/** | ||
* Find a file or a directory upwards. | ||
* | ||
* @param {Test} test | ||
* @param {string} cwd | ||
* @param {(error: Error|null, file?: VFile) => void} callback | ||
* @returns {unknown} | ||
*/ | ||
function (test, cwd, callback) { | ||
return find(test, cwd, callback, true) | ||
} | ||
) | ||
// Find a file or a directory upwards. | ||
function findOne(test, cwd, callback) { | ||
return find(test, cwd, callback, true) | ||
} | ||
// Find files or directories upwards. | ||
function findAll(test, cwd, callback) { | ||
return find(test, cwd, callback) | ||
} | ||
// Find applicable files. | ||
function find(test, cwd, callback, one) { | ||
/** | ||
* Find applicable files. | ||
* | ||
* @param {Test} test | ||
* @param {string|((error: Error|null, result?: VFile|Array.<VFile>) => void)} cwd | ||
* @param {null|undefined|((error: Error|null, result?: VFile|Array.<VFile>) => void)} cb | ||
* @param {boolean} [one] | ||
* @returns {Promise.<VFile|Array.<VFile>>} | ||
*/ | ||
function find(test, cwd, cb, one) { | ||
/** @type {Array.<VFile>} */ | ||
var results = [] | ||
/** @type {string} */ | ||
var current | ||
/** @type {Assert} */ | ||
var assert = convert(test) | ||
/** @type {string} */ | ||
var base | ||
/** @type {(error: Error|null, result?: VFile|Array.<VFile>) => void} */ | ||
var callback | ||
test = augment(test) | ||
if (typeof cwd === 'string') { | ||
base = cwd | ||
callback = cb | ||
} else { | ||
base = null | ||
callback = cwd | ||
} | ||
current = base ? path.resolve(base) : process.cwd() | ||
if (!callback) { | ||
callback = cwd | ||
cwd = null | ||
return new Promise(executor) | ||
} | ||
current = cwd ? resolve(cwd) : process.cwd() | ||
executor(resolve) | ||
once() | ||
/** | ||
* @param {VFile|Array.<VFile>} result | ||
*/ | ||
function resolve(result) { | ||
callback(null, result) | ||
} | ||
// Test a file and check what should be done with the resulting file. | ||
function handle(filePath) { | ||
var file = toVFile(filePath) | ||
var result = test(file) | ||
/** | ||
* @param {(x: VFile|Array.<VFile>) => void} resolve | ||
*/ | ||
function executor(resolve) { | ||
once(current) | ||
if (mask(result, INCLUDE)) { | ||
if (one) { | ||
callback(null, file) | ||
/** | ||
* Test a file and check what should be done with the resulting file. | ||
* | ||
* @param {string} filePath | ||
* @returns {boolean} | ||
*/ | ||
function handle(filePath) { | ||
var file = toVFile(filePath) | ||
var result = Number(assert(file)) | ||
if ((result & INCLUDE) === INCLUDE) { | ||
if (one) { | ||
resolve(file) | ||
return true | ||
} | ||
results.push(file) | ||
} | ||
if ((result & BREAK) === BREAK) { | ||
resolve(one ? null : results) | ||
return true | ||
} | ||
results.push(file) | ||
} | ||
if (mask(result, BREAK)) { | ||
callback(null, one ? null : results) | ||
return true | ||
} | ||
} | ||
/** | ||
* Check one directory. | ||
* | ||
* @param {string} child | ||
* @returns {void} | ||
*/ | ||
function once(child) { | ||
if (handle(current) === true) { | ||
return | ||
} | ||
// Check one directory. | ||
function once(child) { | ||
if (handle(current) === true) { | ||
return | ||
} | ||
fs.readdir(current, function (error, entries) { | ||
var index = -1 | ||
/** @type {string} */ | ||
var entry | ||
readdir(current, onread) | ||
if (error) { | ||
entries = [] | ||
} | ||
function onread(error, entries) { | ||
var length = entries ? entries.length : 0 | ||
var index = -1 | ||
var entry | ||
while (++index < entries.length) { | ||
entry = entries[index] | ||
if (error) { | ||
entries = [] | ||
} | ||
if ( | ||
entry !== child && | ||
handle(path.resolve(current, entry)) === true | ||
) { | ||
return | ||
} | ||
} | ||
while (++index < length) { | ||
entry = entries[index] | ||
child = current | ||
current = path.dirname(current) | ||
if (entry !== child && handle(resolve(current, entry)) === true) { | ||
if (current === child) { | ||
resolve(one ? null : results) | ||
return | ||
} | ||
} | ||
child = current | ||
current = dirname(current) | ||
if (current === child) { | ||
callback(null, one ? null : results) | ||
return | ||
} | ||
once(basename(child)) | ||
once(path.basename(child)) | ||
}) | ||
} | ||
@@ -104,19 +178,29 @@ } | ||
// Augment `test` | ||
function augment(test) { | ||
if (typeof test === 'function') { | ||
return test | ||
} | ||
return typeof test === 'string' ? testString(test) : multiple(test) | ||
/** | ||
* Convert `test` | ||
* | ||
* @param {Test} test | ||
* @returns {Assert} | ||
*/ | ||
function convert(test) { | ||
return typeof test === 'function' | ||
? test | ||
: typeof test === 'string' | ||
? testString(test) | ||
: multiple(test) | ||
} | ||
// Check multiple tests. | ||
/** | ||
* Check multiple tests. | ||
* | ||
* @param {Array.<string|Assert>} test | ||
* @returns {Assert} | ||
*/ | ||
function multiple(test) { | ||
var length = test.length | ||
/** @type {Array.<Assert>} */ | ||
var tests = [] | ||
var index = -1 | ||
var tests = [] | ||
while (++index < length) { | ||
tests[index] = augment(test[index]) | ||
while (++index < test.length) { | ||
tests[index] = convert(test[index]) | ||
} | ||
@@ -126,8 +210,9 @@ | ||
/** @type {Assert} */ | ||
function check(file) { | ||
var index = -1 | ||
/** @type {number|boolean|void} */ | ||
var result | ||
index = -1 | ||
while (++index < length) { | ||
while (++index < tests.length) { | ||
result = tests[index](file) | ||
@@ -144,10 +229,12 @@ | ||
// Wrap a string given as a test. | ||
// | ||
// 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. | ||
/** | ||
* Wrap a string given as a test. | ||
* | ||
* @param {string} test | ||
* @returns {Assert} | ||
*/ | ||
function testString(test) { | ||
return check | ||
/** @type {Assert} */ | ||
function check(file) { | ||
@@ -157,6 +244,1 @@ return test === file.basename || test === file.extname | ||
} | ||
// Check a mask. | ||
function mask(value, bitmask) { | ||
return (value & bitmask) === bitmask | ||
} |
{ | ||
"name": "vfile-find-up", | ||
"version": "5.0.1", | ||
"version": "6.0.0", | ||
"description": "vfile utility to find one or more files by searching the file system upwards", | ||
@@ -28,28 +28,34 @@ "license": "MIT", | ||
], | ||
"sideEffects": false, | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"index.d.ts", | ||
"index.js" | ||
], | ||
"dependencies": { | ||
"to-vfile": "^6.0.0" | ||
"to-vfile": "^7.0.0", | ||
"vfile": "^5.0.0" | ||
}, | ||
"devDependencies": { | ||
"nyc": "^15.0.0", | ||
"prettier": "^1.0.0", | ||
"remark-cli": "^7.0.0", | ||
"remark-preset-wooorm": "^6.0.0", | ||
"tape": "^4.0.0", | ||
"xo": "^0.27.0" | ||
"@types/tape": "^4.0.0", | ||
"c8": "^7.0.0", | ||
"prettier": "^2.0.0", | ||
"remark-cli": "^9.0.0", | ||
"remark-preset-wooorm": "^8.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"xo": "^0.39.0" | ||
}, | ||
"scripts": { | ||
"format": "remark . -qfo && prettier --write \"**/*.js\" && xo --fix", | ||
"test-api": "node test", | ||
"test-coverage": "nyc --reporter lcov tape test/index.js", | ||
"test": "npm run format && npm run test-coverage" | ||
"prepack": "npm run build && npm run format", | ||
"build": "rimraf \"*.d.ts\" && tsc && type-coverage", | ||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", | ||
"test-api": "node test/index.js", | ||
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test/index.js", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
}, | ||
"nyc": { | ||
"check-coverage": true, | ||
"lines": 100, | ||
"functions": 100, | ||
"branches": 100 | ||
}, | ||
"prettier": { | ||
@@ -65,3 +71,6 @@ "tabWidth": 2, | ||
"prettier": true, | ||
"esnext": false | ||
"rules": { | ||
"no-var": "off", | ||
"prefer-arrow-callback": "off" | ||
} | ||
}, | ||
@@ -72,3 +81,8 @@ "remarkConfig": { | ||
] | ||
}, | ||
"typeCoverage": { | ||
"atLeast": 100, | ||
"detail": true, | ||
"strict": true | ||
} | ||
} |
@@ -14,2 +14,5 @@ # vfile-find-up | ||
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): | ||
Node 12+ is needed to use it and it must be `import`ed instead of `require`d. | ||
[npm][]: | ||
@@ -24,5 +27,5 @@ | ||
```js | ||
var findUp = require('vfile-find-up') | ||
import {findUp} from 'vfile-find-up' | ||
findUp.all('package.json', console.log) | ||
findUp('package.json', console.log) | ||
``` | ||
@@ -42,8 +45,17 @@ | ||
### `findUp.all(tests[, path], callback)` | ||
This package exports the following identifiers: `findUp`, `findUpOne`, `INCLUDE`, | ||
`BREAK`. | ||
There is no default export. | ||
### `findUp(tests[, path][, callback])` | ||
Search for `tests` upwards. | ||
Invokes callback with either an error or an array of files passing `tests`. | ||
Calls callback with either an error or an array of files passing `tests`. | ||
Note: Virtual Files are not read (their `contents` is not populated). | ||
##### Sigantures | ||
* `(tests: Test, path?: string, callback: Callback): void` | ||
* `(tests: Test, path?: string): Promise.<Array.<VFile>>` | ||
##### Parameters | ||
@@ -69,7 +81,8 @@ | ||
Function invoked with all matching files (`function cb(err[, files])`). | ||
Function called with all matching files (`function cb(err[, files])`). | ||
### `findUp.one(tests[, path], callback)` | ||
### `findUpOne(tests[, path][, callback])` | ||
Like `findUp.all`, but invokes `callback` with the first found file, or `null`. | ||
Like `findUp`, but either calls `callback` with the first found file, or `null` | ||
or without callback resolves to a file or `null`. | ||
@@ -79,12 +92,12 @@ ### `function test(file)` | ||
Check whether a virtual file should be included. | ||
Invoked with a [vfile][]. | ||
Called with a [vfile][]. | ||
##### Returns | ||
* `true` or `findUp.INCLUDE` — Include the file in the results | ||
* `findUp.BREAK` — Stop searching for files | ||
* `true` or `INCLUDE` — Include the file in the results | ||
* `BREAK` — Stop searching for files | ||
* anything else is ignored: the file is not included | ||
The different flags can be combined by using the pipe operator: | ||
`findUp.INCLUDE | findUp.BREAK`. | ||
`INCLUDE | BREAK`. | ||
@@ -107,5 +120,5 @@ ## Contribute | ||
[build-badge]: https://img.shields.io/travis/vfile/vfile-find-up.svg | ||
[build-badge]: https://github.com/vfile/vfile-find-up/workflows/main/badge.svg | ||
[build]: https://travis-ci.org/vfile/vfile-find-up | ||
[build]: https://github.com/vfile/vfile-find-up/actions | ||
@@ -126,15 +139,15 @@ [coverage-badge]: https://img.shields.io/codecov/c/github/vfile/vfile-find-up.svg | ||
[chat-badge]: https://img.shields.io/badge/chat-spectrum-7b16ff.svg | ||
[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg | ||
[chat]: https://spectrum.chat/unified/vfile | ||
[chat]: https://github.com/vfile/vfile/discussions | ||
[npm]: https://docs.npmjs.com/cli/install | ||
[contributing]: https://github.com/vfile/.github/blob/master/contributing.md | ||
[contributing]: https://github.com/vfile/.github/blob/HEAD/contributing.md | ||
[support]: https://github.com/vfile/.github/blob/master/support.md | ||
[support]: https://github.com/vfile/.github/blob/HEAD/support.md | ||
[health]: https://github.com/vfile/.github | ||
[coc]: https://github.com/vfile/.github/blob/master/code-of-conduct.md | ||
[coc]: https://github.com/vfile/.github/blob/HEAD/code-of-conduct.md | ||
@@ -141,0 +154,0 @@ [license]: license |
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
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
12746
5
233
154
Yes
2
10
1
+ Addedvfile@^5.0.0
+ Addedto-vfile@7.2.4(transitive)
+ Addedunist-util-stringify-position@3.0.3(transitive)
+ Addedvfile@5.3.7(transitive)
+ Addedvfile-message@3.1.4(transitive)
- Removedto-vfile@6.1.0(transitive)
- Removedunist-util-stringify-position@2.0.3(transitive)
- Removedvfile@4.2.1(transitive)
- Removedvfile-message@2.0.4(transitive)
Updatedto-vfile@^7.0.0