diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 72ba183..9ef476d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: node: - - lts/hydrogen + - lts/jod - node os: - ubuntu-latest diff --git a/lib/finder.js b/lib/finder.js index bb55089..38917d4 100644 --- a/lib/finder.js +++ b/lib/finder.js @@ -96,8 +96,8 @@ import path from 'node:path' import fs from 'node:fs' -import {glob, hasMagic} from 'glob' import ignore_ from 'ignore' +import {Minimatch} from 'minimatch' import {VFile} from 'vfile' // @ts-expect-error: types of `ignore` are wrong. @@ -154,38 +154,30 @@ function expand(input, options, next) { while (++index < input.length) { let file = input[index] if (typeof file === 'string') { - if (hasMagic(file)) { + // Default options, where `\` escapes: `fs.glob` treats `\` as a path + // separator, which would turn Windows paths like `a\[b]\c.md` into globs. + if (new Minimatch(file).hasMagic()) { expected++ - glob(file, {cwd: options.cwd}).then( - function (files) { - /* c8 ignore next 3 -- glob errors are unusual. */ - if (failed) { - return - } - - actual++ - paths.push(...files) - - if (actual === expected) { - search(paths, options, done1) - } - }, - /** - * @param {Error} error - * Error. - * @returns {undefined} - * Nothing. - */ - /* c8 ignore next 8 -- glob errors are unusual. */ - function (error) { - if (failed) { - return - } + fs.glob(file, {cwd: options.cwd}, function (error, files) { + /* c8 ignore next 3 -- glob errors are unusual. */ + if (failed) { + return + } + /* c8 ignore next 5 -- glob errors are unusual. */ + if (error) { failed = true done1(error) + return + } + + actual++ + paths.push(...files) + + if (actual === expected) { + search(paths, options, done1) } - ) + }) } else { // `relative` to make the paths canonical. file = diff --git a/package.json b/package.json index 205d972..502033c 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,11 @@ "concat-stream": "^2.0.0", "debug": "^4.0.0", "extend": "^3.0.0", - "glob": "^10.0.0", "ignore": "^7.0.0", "is-empty": "^1.0.0", "is-plain-obj": "^4.0.0", "load-plugin": "^6.0.0", + "minimatch": "^10.0.0", "parse-json": "^7.0.0", "trough": "^2.0.0", "unist-util-inspect": "^8.0.0", diff --git a/readme.md b/readme.md index e86a92f..119f1e1 100644 --- a/readme.md +++ b/readme.md @@ -106,7 +106,7 @@ You can use this to make such things. ## Install This package is [ESM only][esm]. -In Node.js (version 16+), install with [npm][]: +In Node.js (version 22.17+), install with [npm][]: ```sh npm install unified-engine @@ -1569,8 +1569,8 @@ versions of Node.js. When we cut a new major release, we drop support for unmaintained versions of Node. -This means we try to keep the current release line, `unified-engine@^11`, -compatible with Node.js 16. +This means we try to keep the current release line, `unified-engine@^12`, +compatible with Node.js 22.17+. ## Security diff --git a/test/fixtures/globs-symlink/folder/one.txt b/test/fixtures/globs-symlink/folder/one.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/input.js b/test/input.js index 1e90dcd..be9ccad 100644 --- a/test/input.js +++ b/test/input.js @@ -233,6 +233,33 @@ test('input', async function (t) { ) }) + await t.test( + 'should not follow symlinked folders in globs', + async function () { + const cwd = new URL('globs-symlink/', fixtures) + const link = new URL('link', cwd) + const stderr = spy() + + // Remove a link left behind by an earlier, interrupted run. + await fs.rm(link, {force: true}) + // Junction, so that Windows needs no extra permissions. + await fs.symlink(new URL('folder', cwd), link, 'junction') + + const result = await engine({ + cwd, + extensions: [], + files: ['*/*.txt'], + processor: noop, + streamError: stderr.stream + }) + + await fs.unlink(link) + + assert.equal(result.code, 0) + assert.equal(stderr(), 'folder' + path.sep + 'one.txt: no issues found\n') + } + ) + await t.test('should search vfile’s pointing to folders', async function () { const cwd = new URL('ignore-file/', fixtures) const stderr = spy()