diff --git a/.ci/.azure-pipelines-steps.yml b/.ci/.azure-pipelines-steps.yml deleted file mode 100644 index 59369c3..0000000 --- a/.ci/.azure-pipelines-steps.yml +++ /dev/null @@ -1,34 +0,0 @@ -steps: -- script: npm i -g npm@$(npm_version) - displayName: Use non-broken npm version $(npm_version) - condition: ne(variables['npm_version'], '') - -- task: NodeTool@0 - inputs: - versionSpec: '$(node_version)' - displayName: Use Node $(node_version) - -- script: npm install - displayName: npm install - -- script: npm test - displayName: Run tests - -- script: npm run coveralls - displayName: Run coveralls - env: - COVERALLS_SERVICE_NAME: Azure Pipelines - COVERALLS_SERVICE_NUMBER: $(Build.BuildNumber) - COVERALLS_SERVICE_JOB_ID: "$(Agent.OS)_$(node_version)" - COVERALLS_GIT_BRANCH: $(Build.SourceBranchName) - COVERALLS_REPO_TOKEN: $(COVERALLS_REPO_TOKEN_SECRET) - COVERALLS_PARALLEL: true - CI_PULL_REQUEST: $(System.PullRequest.PullRequestNumber) - -- script: npm run azure-pipelines - displayName: Write tests to xml - -- task: PublishTestResults@2 - inputs: - testResultsFiles: '**/test.xunit' - condition: succeededOrFailed() diff --git a/.ci/.azure-pipelines.yml b/.ci/.azure-pipelines.yml deleted file mode 100644 index 195683a..0000000 --- a/.ci/.azure-pipelines.yml +++ /dev/null @@ -1,65 +0,0 @@ -trigger: -- master -- releases/* - -jobs: - - job: Test_Linux - displayName: Run Tests on Linux - pool: - vmImage: "Ubuntu 16.04" - strategy: - matrix: - Node_v10: - node_version: 10 - Node_v8: - node_version: 8 - Node_v6: - node_version: 6 - steps: - - template: .azure-pipelines-steps.yml - - - job: Test_Windows - displayName: Run Tests on Windows - pool: - vmImage: "windows-2019" - strategy: - matrix: - Node_v10: - node_version: 10 - npm_version: 6.4.1 - Node_v8: - node_version: 8 - npm_version: 6.4.1 - Node_v6: - node_version: 6 - steps: - - template: .azure-pipelines-steps.yml - - - job: Test_MacOS - displayName: Run Tests on MacOS - pool: - vmImage: "macOS-10.15" - strategy: - matrix: - Node_v10: - node_version: 10 - Node_v8: - node_version: 8 - Node_v6: - node_version: 6 - steps: - - template: .azure-pipelines-steps.yml - - - job: Notify_Coveralls - displayName: Notify Coveralls that the parallel report is done - pool: - vmImage: "Ubuntu 16.04" - dependsOn: - - Test_Linux - - Test_Windows - - Test_MacOS - steps: - - script: curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$BUILD_NAME&payload[status]=done" - env: - COVERALLS_REPO_TOKEN: $(COVERALLS_REPO_TOKEN_SECRET) - BUILD_NAME: $(Build.BuildNumber) diff --git a/.github/support.yml b/.github/support.yml deleted file mode 100644 index cd6325e..0000000 --- a/.github/support.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Configuration for support-requests - https://github.com/dessant/support-requests -supportLabel: support -supportComment: > - Issues are reserved for bugs and features. Here are a few places to find answers to your question: - - * For community support, use the `gulp` tag on [StackOverflow](https://stackoverflow.com/questions/tagged/gulp). - - * Participate in community chat on [Gitter](https://gitter.im/gulpjs/gulp). - - * To get paid support directly from the maintainers, sign up for [Tidelift](https://tidelift.com/subscription/pkg/npm-gulp?utm_source=npm-gulp&utm_medium=referral&utm_campaign=support). Subscribers should email support@tidelift.com, mention that it's a question for Gulp, and describe your question. Straightforward questions are answered as part of your subscription. Additional consulting hours are available for more complex help. -close: true -lock: false -setLockReason: false diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 0000000..5ea4cad --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,74 @@ +name: dev +on: + pull_request: + push: + branches: + - main +env: + CI: true + +jobs: + prettier: + name: Format code + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Prettier + uses: gulpjs/prettier_action@v3.0 + with: + commit_message: 'chore: Run prettier' + prettier_options: '--write .' + + test: + name: Tests for Node ${{ matrix.node }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + node: [10, 12, 14] + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Clone repository + uses: actions/checkout@v2 + + - name: Set Node.js version + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + + - run: node --version + - run: npm --version + + - name: Install npm dependencies + run: npm install + + - name: Run lint + run: npm run lint + + - name: Run tests + run: npm test + + - name: Coveralls + uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: ${{matrix.os}}-node-${{ matrix.node }} + parallel: true + + coveralls: + needs: test + name: Finish up + + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..25dd115 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,15 @@ +name: release +on: + push: + branches: + - main + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: GoogleCloudPlatform/release-please-action@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-type: node + package-name: release-please-action diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ed88d37 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +coverage/ +.nyc_output/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ff53345..0000000 --- a/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -sudo: false -language: node_js -node_js: - - '10' - - '8' - - '6' -after_script: - - npm run coveralls diff --git a/CHANGELOG.md b/CHANGELOG.md index fb9de96..54415cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,110 +1,113 @@ ### [5.1.2](https://github.com/gulpjs/glob-parent/compare/v5.1.1...v5.1.2) (2021-03-06) +### Bug Fixes + +- eliminate ReDoS ([#36](https://github.com/gulpjs/glob-parent/issues/36)) ([f923116](https://github.com/gulpjs/glob-parent/commit/f9231168b0041fea3f8f954b3cceb56269fc6366)) + +## [6.0.0](https://www.github.com/gulpjs/glob-parent/compare/v5.1.2...v6.0.0) (2021-05-03) + + +### ⚠ BREAKING CHANGES + +* Correct mishandled escaped path separators (#34) +* upgrade scaffold, dropping node <10 support ### Bug Fixes -* eliminate ReDoS ([#36](https://github.com/gulpjs/glob-parent/issues/36)) ([f923116](https://github.com/gulpjs/glob-parent/commit/f9231168b0041fea3f8f954b3cceb56269fc6366)) +* Correct mishandled escaped path separators ([#34](https://www.github.com/gulpjs/glob-parent/issues/34)) ([32f6d52](https://www.github.com/gulpjs/glob-parent/commit/32f6d52663b7addac38d0dff570d8127edf03f47)), closes [#32](https://www.github.com/gulpjs/glob-parent/issues/32) -### [5.1.1](https://github.com/gulpjs/glob-parent/compare/v5.1.0...v5.1.1) (2021-01-27) +### Miscellaneous Chores + +* upgrade scaffold, dropping node <10 support ([e83d0c5](https://www.github.com/gulpjs/glob-parent/commit/e83d0c5a411947cf69eb58f36349db80439c606f)) + +### [5.1.1](https://github.com/gulpjs/glob-parent/compare/v5.1.0...v5.1.1) (2021-01-27) ### Bug Fixes -* unescape exclamation mark ([#26](https://github.com/gulpjs/glob-parent/issues/26)) ([a98874f](https://github.com/gulpjs/glob-parent/commit/a98874f1a59e407f4fb1beb0db4efa8392da60bb)) +- unescape exclamation mark ([#26](https://github.com/gulpjs/glob-parent/issues/26)) ([a98874f](https://github.com/gulpjs/glob-parent/commit/a98874f1a59e407f4fb1beb0db4efa8392da60bb)) ## [5.1.0](https://github.com/gulpjs/glob-parent/compare/v5.0.0...v5.1.0) (2021-01-27) - ### Features -* add `flipBackslashes` option to disable auto conversion of slashes (closes [#24](https://github.com/gulpjs/glob-parent/issues/24)) ([#25](https://github.com/gulpjs/glob-parent/issues/25)) ([eecf91d](https://github.com/gulpjs/glob-parent/commit/eecf91d5e3834ed78aee39c4eaaae654d76b87b3)) +- add `flipBackslashes` option to disable auto conversion of slashes (closes [#24](https://github.com/gulpjs/glob-parent/issues/24)) ([#25](https://github.com/gulpjs/glob-parent/issues/25)) ([eecf91d](https://github.com/gulpjs/glob-parent/commit/eecf91d5e3834ed78aee39c4eaaae654d76b87b3)) ## [5.0.0](https://github.com/gulpjs/glob-parent/compare/v4.0.0...v5.0.0) (2021-01-27) - ### ⚠ BREAKING CHANGES -* Drop support for node <6 & bump dependencies +- Drop support for node <6 & bump dependencies ### Miscellaneous Chores -* Drop support for node <6 & bump dependencies ([896c0c0](https://github.com/gulpjs/glob-parent/commit/896c0c00b4e7362f60b96e7fc295ae929245255a)) +- Drop support for node <6 & bump dependencies ([896c0c0](https://github.com/gulpjs/glob-parent/commit/896c0c00b4e7362f60b96e7fc295ae929245255a)) ## [4.0.0](https://github.com/gulpjs/glob-parent/compare/v3.1.0...v4.0.0) (2021-01-27) - ### ⚠ BREAKING CHANGES -* question marks are valid path characters on Windows so avoid flagging as a glob when alone -* Update is-glob dependency +- question marks are valid path characters on Windows so avoid flagging as a glob when alone +- Update is-glob dependency ### Features -* hoist regexps and strings for performance gains ([4a80667](https://github.com/gulpjs/glob-parent/commit/4a80667c69355c76a572a5892b0f133c8e1f457e)) -* question marks are valid path characters on Windows so avoid flagging as a glob when alone ([2a551dd](https://github.com/gulpjs/glob-parent/commit/2a551dd0dc3235e78bf3c94843d4107072d17841)) -* Update is-glob dependency ([e41fcd8](https://github.com/gulpjs/glob-parent/commit/e41fcd895d1f7bc617dba45c9d935a7949b9c281)) +- hoist regexps and strings for performance gains ([4a80667](https://github.com/gulpjs/glob-parent/commit/4a80667c69355c76a572a5892b0f133c8e1f457e)) +- question marks are valid path characters on Windows so avoid flagging as a glob when alone ([2a551dd](https://github.com/gulpjs/glob-parent/commit/2a551dd0dc3235e78bf3c94843d4107072d17841)) +- Update is-glob dependency ([e41fcd8](https://github.com/gulpjs/glob-parent/commit/e41fcd895d1f7bc617dba45c9d935a7949b9c281)) ## [3.1.0](https://github.com/gulpjs/glob-parent/compare/v3.0.1...v3.1.0) (2021-01-27) - ### Features -* allow basic win32 backslash use ([272afa5](https://github.com/gulpjs/glob-parent/commit/272afa5fd070fc0f796386a5993d4ee4a846988b)) -* handle extglobs (parentheses) containing separators ([7db1bdb](https://github.com/gulpjs/glob-parent/commit/7db1bdb0756e55fd14619e8ce31aa31b17b117fd)) -* new approach to braces/brackets handling ([8269bd8](https://github.com/gulpjs/glob-parent/commit/8269bd89290d99fac9395a354fb56fdcdb80f0be)) -* pre-process braces/brackets sections ([9ef8a87](https://github.com/gulpjs/glob-parent/commit/9ef8a87f66b1a43d0591e7a8e4fc5a18415ee388)) -* preserve escaped brace/bracket at end of string ([8cfb0ba](https://github.com/gulpjs/glob-parent/commit/8cfb0ba84202d51571340dcbaf61b79d16a26c76)) - +- allow basic win32 backslash use ([272afa5](https://github.com/gulpjs/glob-parent/commit/272afa5fd070fc0f796386a5993d4ee4a846988b)) +- handle extglobs (parentheses) containing separators ([7db1bdb](https://github.com/gulpjs/glob-parent/commit/7db1bdb0756e55fd14619e8ce31aa31b17b117fd)) +- new approach to braces/brackets handling ([8269bd8](https://github.com/gulpjs/glob-parent/commit/8269bd89290d99fac9395a354fb56fdcdb80f0be)) +- pre-process braces/brackets sections ([9ef8a87](https://github.com/gulpjs/glob-parent/commit/9ef8a87f66b1a43d0591e7a8e4fc5a18415ee388)) +- preserve escaped brace/bracket at end of string ([8cfb0ba](https://github.com/gulpjs/glob-parent/commit/8cfb0ba84202d51571340dcbaf61b79d16a26c76)) ### Bug Fixes -* trailing escaped square brackets ([99ec9fe](https://github.com/gulpjs/glob-parent/commit/99ec9fecc60ee488ded20a94dd4f18b4f55c4ccf)) +- trailing escaped square brackets ([99ec9fe](https://github.com/gulpjs/glob-parent/commit/99ec9fecc60ee488ded20a94dd4f18b4f55c4ccf)) ### [3.0.1](https://github.com/gulpjs/glob-parent/compare/v3.0.0...v3.0.1) (2021-01-27) - ### Features -* use path-dirname ponyfill ([cdbea5f](https://github.com/gulpjs/glob-parent/commit/cdbea5f32a58a54e001a75ddd7c0fccd4776aacc)) - +- use path-dirname ponyfill ([cdbea5f](https://github.com/gulpjs/glob-parent/commit/cdbea5f32a58a54e001a75ddd7c0fccd4776aacc)) ### Bug Fixes -* unescape glob-escaped dirnames on output ([598c533](https://github.com/gulpjs/glob-parent/commit/598c533bdf49c1428bc063aa9b8db40c5a86b030)) +- unescape glob-escaped dirnames on output ([598c533](https://github.com/gulpjs/glob-parent/commit/598c533bdf49c1428bc063aa9b8db40c5a86b030)) ## [3.0.0](https://github.com/gulpjs/glob-parent/compare/v2.0.0...v3.0.0) (2021-01-27) - ### ⚠ BREAKING CHANGES -* update is-glob dependency +- update is-glob dependency ### Features -* update is-glob dependency ([5c5f8ef](https://github.com/gulpjs/glob-parent/commit/5c5f8efcee362a8e7638cf8220666acd8784f6bd)) +- update is-glob dependency ([5c5f8ef](https://github.com/gulpjs/glob-parent/commit/5c5f8efcee362a8e7638cf8220666acd8784f6bd)) ## [2.0.0](https://github.com/gulpjs/glob-parent/compare/v1.3.0...v2.0.0) (2021-01-27) - ### Features -* move up to dirname regardless of glob characters ([f97fb83](https://github.com/gulpjs/glob-parent/commit/f97fb83be2e0a9fc8d3b760e789d2ecadd6aa0c2)) +- move up to dirname regardless of glob characters ([f97fb83](https://github.com/gulpjs/glob-parent/commit/f97fb83be2e0a9fc8d3b760e789d2ecadd6aa0c2)) ## [1.3.0](https://github.com/gulpjs/glob-parent/compare/v1.2.0...v1.3.0) (2021-01-27) ## [1.2.0](https://github.com/gulpjs/glob-parent/compare/v1.1.0...v1.2.0) (2021-01-27) - ### Reverts -* feat: make regex test strings smaller ([dc80fa9](https://github.com/gulpjs/glob-parent/commit/dc80fa9658dca20549cfeba44bbd37d5246fcce0)) +- feat: make regex test strings smaller ([dc80fa9](https://github.com/gulpjs/glob-parent/commit/dc80fa9658dca20549cfeba44bbd37d5246fcce0)) ## [1.1.0](https://github.com/gulpjs/glob-parent/compare/v1.0.0...v1.1.0) (2021-01-27) - ### Features -* make regex test strings smaller ([cd83220](https://github.com/gulpjs/glob-parent/commit/cd832208638f45169f986d80fcf66e401f35d233)) +- make regex test strings smaller ([cd83220](https://github.com/gulpjs/glob-parent/commit/cd832208638f45169f986d80fcf66e401f35d233)) ## 1.0.0 (2021-01-27) - diff --git a/LICENSE b/LICENSE index 63222d7..d701b08 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The ISC License -Copyright (c) 2015, 2019 Elan Shanker +Copyright (c) 2015, 2019 Elan Shanker, 2021 Blaine Bublitz , Eric Schoffstall and other contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/README.md b/README.md index 36a2793..6ae18a1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # glob-parent -[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Azure Pipelines Build Status][azure-pipelines-image]][azure-pipelines-url] [![Travis Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url] +[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Coveralls Status][coveralls-image]][coveralls-url] Extract the non-magic parent path from a glob string. @@ -45,7 +45,7 @@ Takes a string and returns the part of the path before the glob begins. Be aware ```js { // Disables the automatic conversion of slashes for Windows - flipBackslashes: true + flipBackslashes: true; } ``` @@ -66,13 +66,14 @@ The following characters have special significance in glob patterns and must be **Example** ```js -globParent('foo/[bar]/') // 'foo' -globParent('foo/\\[bar]/') // 'foo/[bar]' +globParent('foo/[bar]/'); // 'foo' +globParent('foo/\\[bar]/'); // 'foo/[bar]' ``` ## Limitations ### Braces & Brackets + This library attempts a quick and imperfect method of determining which path parts have glob magic without fully parsing/lexing the pattern. There are some advanced use cases that can trip it up, such as nested braces where the outer @@ -82,6 +83,7 @@ ensure higher-fidelity glob handling in your library, it is recommended that you pre-process your input with [expand-braces] and/or [expand-brackets]. ### Windows + Backslashes are not valid path separators for globs. If a path with backslashes is provided anyway, for simple cases, glob-parent will replace the path separator for you and return the non-glob parent path (now with @@ -91,10 +93,10 @@ This cannot be used in conjunction with escape characters. ```js // BAD -globParent('C:\\Program Files \\(x86\\)\\*.ext') // 'C:/Program Files /(x86/)' +globParent('C:\\Program Files \\(x86\\)\\*.ext'); // 'C:/Program Files /(x86/)' // GOOD -globParent('C:/Program Files\\(x86\\)/*.ext') // 'C:/Program Files (x86)' +globParent('C:/Program Files\\(x86\\)/*.ext'); // 'C:/Program Files (x86)' ``` If you are using escape characters for a pattern without path parts (i.e. @@ -102,36 +104,31 @@ relative to `cwd`), prefix with `./` to avoid confusing glob-parent. ```js // BAD -globParent('foo \\[bar]') // 'foo ' -globParent('foo \\[bar]*') // 'foo ' +globParent('foo \\[bar]'); // 'foo ' +globParent('foo \\[bar]*'); // 'foo ' // GOOD -globParent('./foo \\[bar]') // 'foo [bar]' -globParent('./foo \\[bar]*') // '.' +globParent('./foo \\[bar]'); // 'foo [bar]' +globParent('./foo \\[bar]*'); // '.' ``` ## License ISC -[expand-braces]: https://github.com/jonschlinkert/expand-braces -[expand-brackets]: https://github.com/jonschlinkert/expand-brackets - -[downloads-image]: https://img.shields.io/npm/dm/glob-parent.svg + +[downloads-image]: https://img.shields.io/npm/dm/glob-parent.svg?style=flat-square [npm-url]: https://www.npmjs.com/package/glob-parent -[npm-image]: https://img.shields.io/npm/v/glob-parent.svg +[npm-image]: https://img.shields.io/npm/v/glob-parent.svg?style=flat-square -[azure-pipelines-url]: https://dev.azure.com/gulpjs/gulp/_build/latest?definitionId=2&branchName=master -[azure-pipelines-image]: https://dev.azure.com/gulpjs/gulp/_apis/build/status/glob-parent?branchName=master - -[travis-url]: https://travis-ci.org/gulpjs/glob-parent -[travis-image]: https://img.shields.io/travis/gulpjs/glob-parent.svg?label=travis-ci - -[appveyor-url]: https://ci.appveyor.com/project/gulpjs/glob-parent -[appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/glob-parent.svg?label=appveyor +[ci-url]: https://github.com/gulpjs/glob-parent/actions?query=workflow:dev +[ci-image]: https://img.shields.io/github/workflow/status/gulpjs/glob-parent/dev?style=flat-square [coveralls-url]: https://coveralls.io/r/gulpjs/glob-parent -[coveralls-image]: https://img.shields.io/coveralls/gulpjs/glob-parent/master.svg +[coveralls-image]: https://img.shields.io/coveralls/gulpjs/glob-parent/master.svg?style=flat-square + -[gitter-url]: https://gitter.im/gulpjs/gulp -[gitter-image]: https://badges.gitter.im/gulpjs/gulp.svg + +[expand-braces]: https://github.com/jonschlinkert/expand-braces +[expand-brackets]: https://github.com/jonschlinkert/expand-brackets + diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index f6cfcfb..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,24 +0,0 @@ -# https://www.appveyor.com/docs/appveyor-yml -# https://www.appveyor.com/docs/lang/nodejs-iojs - -environment: - matrix: - # node.js - - nodejs_version: "6" - - nodejs_version: "8" - - nodejs_version: "10" - -install: - - ps: Install-Product node $env:nodejs_version - - npm install -g npm@6.4.1 - - npm install - -test_script: - - node --version - - npm --version - - cmd: npm test - -build: off - -# build version format -version: "{build}" diff --git a/index.js b/index.js index 09e257e..f861468 100644 --- a/index.js +++ b/index.js @@ -6,15 +6,14 @@ var isWin32 = require('os').platform() === 'win32'; var slash = '/'; var backslash = /\\/g; -var enclosure = /[\{\[].*[\}\]]$/; -var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; -var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; +var enclosure = /[{[].*\/.*[}\]]$/; +var globby = /(^|[^\\])([{[]|\([^)]+$)/; +var escaped = /\\([!*?|[\](){}])/g; /** * @param {string} str * @param {Object} opts * @param {boolean} [opts.flipBackslashes=true] - * @returns {string} */ module.exports = function globParent(str, opts) { var options = Object.assign({ flipBackslashes: true }, opts); diff --git a/package.json b/package.json index 125c971..86699da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "glob-parent", - "version": "5.1.2", + "version": "6.0.0", "description": "Extract the non-magic parent path from a glob string.", "author": "Gulp Team (https://gulpjs.com/)", "contributors": [ @@ -10,7 +10,7 @@ "repository": "gulpjs/glob-parent", "license": "ISC", "engines": { - "node": ">= 6" + "node": ">=10.13.0" }, "main": "index.js", "files": [ @@ -20,20 +20,26 @@ "scripts": { "lint": "eslint .", "pretest": "npm run lint", - "test": "nyc mocha --async-only", - "azure-pipelines": "nyc mocha --async-only --reporter xunit -O output=test.xunit", - "coveralls": "nyc report --reporter=text-lcov | coveralls" + "test": "nyc mocha --async-only" }, "dependencies": { "is-glob": "^4.0.1" }, "devDependencies": { - "coveralls": "^3.0.11", - "eslint": "^2.13.1", - "eslint-config-gulp": "^3.0.1", - "expect": "^1.20.2", - "mocha": "^6.0.2", - "nyc": "^13.3.0" + "eslint": "^7.0.0", + "eslint-config-gulp": "^5.0.0", + "expect": "^26.0.1", + "mocha": "^7.1.2", + "nyc": "^15.0.1" + }, + "nyc": { + "reporter": [ + "lcov", + "text-summary" + ] + }, + "prettier": { + "singleQuote": true }, "keywords": [ "glob", diff --git a/test/.eslintrc b/test/.eslintrc deleted file mode 100644 index 06b940f..0000000 --- a/test/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "gulp/test" -} diff --git a/test/.gitkeep b/test/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/index.test.js b/test/index.test.js index 0a0291e..9cd8eb5 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,216 +1,224 @@ 'use strict'; var gp = require('../'); -var assert = require('assert'); +var expect = require('expect'); var isWin32 = require('os').platform() === 'win32'; -describe('glob-parent', function() { - it('should strip glob magic to return parent path', function(done) { - assert.equal(gp('.'), '.'); - assert.equal(gp('.*'), '.'); - assert.equal(gp('/.*'), '/'); - assert.equal(gp('/.*/'), '/'); - assert.equal(gp('a/.*/b'), 'a'); - assert.equal(gp('a*/.*/b'), '.'); - assert.equal(gp('*/a/b/c'), '.'); - assert.equal(gp('*'), '.'); - assert.equal(gp('*/'), '.'); - assert.equal(gp('*/*'), '.'); - assert.equal(gp('*/*/'), '.'); - assert.equal(gp('**'), '.'); - assert.equal(gp('**/'), '.'); - assert.equal(gp('**/*'), '.'); - assert.equal(gp('**/*/'), '.'); - assert.equal(gp('/*.js'), '/'); - assert.equal(gp('*.js'), '.'); - assert.equal(gp('**/*.js'), '.'); - assert.equal(gp('{a,b}'), '.'); - assert.equal(gp('/{a,b}'), '/'); - assert.equal(gp('/{a,b}/'), '/'); - assert.equal(gp('(a|b)'), '.'); - assert.equal(gp('/(a|b)'), '/'); - assert.equal(gp('./(a|b)'), '.'); - assert.equal(gp('a/(b c)'), 'a', 'not an extglob'); - assert.equal(gp('a/(b c)/'), 'a/(b c)', 'not an extglob'); - assert.equal(gp('a/(b c)/d'), 'a/(b c)', 'not an extglob'); - assert.equal(gp('path/to/*.js'), 'path/to'); - assert.equal(gp('/root/path/to/*.js'), '/root/path/to'); - assert.equal(gp('chapter/foo [bar]/'), 'chapter'); - assert.equal(gp('path/[a-z]'), 'path'); - assert.equal(gp('[a-z]'), '.'); - assert.equal(gp('path/{to,from}'), 'path'); - assert.equal(gp('path/(to|from)'), 'path'); - assert.equal(gp('path/(foo bar)/subdir/foo.*'), 'path/(foo bar)/subdir'); - assert.equal(gp('path/!(to|from)'), 'path'); - assert.equal(gp('path/?(to|from)'), 'path'); - assert.equal(gp('path/+(to|from)'), 'path'); - assert.equal(gp('path/*(to|from)'), 'path'); - assert.equal(gp('path/@(to|from)'), 'path'); - assert.equal(gp('path/!/foo'), 'path/!'); - assert.equal(gp('path/?/foo'), 'path/?'); - assert.equal(gp('path/+/foo'), 'path/+'); - assert.equal(gp('path/*/foo'), 'path'); - assert.equal(gp('path/@/foo'), 'path/@'); - assert.equal(gp('path/!/foo/'), 'path/!/foo'); - assert.equal(gp('path/?/foo/'), 'path/?/foo'); - assert.equal(gp('path/+/foo/'), 'path/+/foo'); - assert.equal(gp('path/*/foo/'), 'path'); - assert.equal(gp('path/@/foo/'), 'path/@/foo'); - assert.equal(gp('path/**/*'), 'path'); - assert.equal(gp('path/**/subdir/foo.*'), 'path'); - assert.equal(gp('path/subdir/**/foo.js'), 'path/subdir'); - assert.equal(gp('path/!subdir/foo.js'), 'path/!subdir'); - assert.equal(gp('path/{foo,bar}/'), 'path'); - - done(); - }); - - it('should respect escaped characters', function(done) { - assert.equal(gp('path/\\*\\*/subdir/foo.*'), 'path/**/subdir'); - assert.equal(gp('path/\\[\\*\\]/subdir/foo.*'), 'path/[*]/subdir'); - assert.equal(gp('path/\\*(a|b)/subdir/foo.*'), 'path'); - assert.equal(gp('path/\\*/(a|b)/subdir/foo.*'), 'path/*'); - assert.equal(gp('path/\\*\\(a\\|b\\)/subdir/foo.*'), 'path/*(a|b)/subdir'); - assert.equal(gp('path/\\[foo bar\\]/subdir/foo.*'), 'path/[foo bar]/subdir'); - assert.equal(gp('path/\\[bar]/'), 'path/[bar]'); - assert.equal(gp('path/\\[bar]'), 'path/[bar]'); - assert.equal(gp('[bar]'), '.'); - assert.equal(gp('[bar]/'), '.'); - assert.equal(gp('./\\[bar]'), './[bar]'); - assert.equal(gp('\\[bar]/'), '[bar]'); - assert.equal(gp('\\!dir/*'), '!dir'); - assert.equal(gp('[bar\\]/'), '.'); - assert.equal(gp('path/foo \\[bar]/'), 'path/foo [bar]'); - assert.equal(gp('path/\\{foo,bar}/'), 'path/{foo,bar}'); - assert.equal(gp('\\{foo,bar}/'), '{foo,bar}'); - assert.equal(gp('\\{foo,bar\\}/'), '{foo,bar}'); - assert.equal(gp('{foo,bar\\}/'), '.'); +describe('glob-parent', function () { + it('should strip glob magic to return parent path', function (done) { + expect(gp('.')).toEqual('.'); + expect(gp('.*')).toEqual('.'); + expect(gp('/.*')).toEqual('/'); + expect(gp('/.*/')).toEqual('/'); + expect(gp('a/.*/b')).toEqual('a'); + expect(gp('a*/.*/b')).toEqual('.'); + expect(gp('*/a/b/c')).toEqual('.'); + expect(gp('*')).toEqual('.'); + expect(gp('*/')).toEqual('.'); + expect(gp('*/*')).toEqual('.'); + expect(gp('*/*/')).toEqual('.'); + expect(gp('**')).toEqual('.'); + expect(gp('**/')).toEqual('.'); + expect(gp('**/*')).toEqual('.'); + expect(gp('**/*/')).toEqual('.'); + expect(gp('/*.js')).toEqual('/'); + expect(gp('*.js')).toEqual('.'); + expect(gp('**/*.js')).toEqual('.'); + expect(gp('{a,b}')).toEqual('.'); + expect(gp('/{a,b}')).toEqual('/'); + expect(gp('/{a,b}/')).toEqual('/'); + expect(gp('(a|b)')).toEqual('.'); + expect(gp('/(a|b)')).toEqual('/'); + expect(gp('./(a|b)')).toEqual('.'); + expect(gp('a/(b c)')).toEqual('a'); // not an extglob + expect(gp('a/(b c)/')).toEqual('a/(b c)'); // not an extglob + expect(gp('a/(b c)/d')).toEqual('a/(b c)'); // not an extglob + expect(gp('path/to/*.js')).toEqual('path/to'); + expect(gp('/root/path/to/*.js')).toEqual('/root/path/to'); + expect(gp('chapter/foo [bar]/')).toEqual('chapter'); + expect(gp('path/[a-z]')).toEqual('path'); + expect(gp('[a-z]')).toEqual('.'); + expect(gp('path/{to,from}')).toEqual('path'); + expect(gp('path/(to|from)')).toEqual('path'); + expect(gp('path/(foo bar)/subdir/foo.*')).toEqual('path/(foo bar)/subdir'); + expect(gp('path/!(to|from)')).toEqual('path'); + expect(gp('path/?(to|from)')).toEqual('path'); + expect(gp('path/+(to|from)')).toEqual('path'); + expect(gp('path/*(to|from)')).toEqual('path'); + expect(gp('path/@(to|from)')).toEqual('path'); + expect(gp('path/!/foo')).toEqual('path/!'); + expect(gp('path/?/foo')).toEqual('path/?'); + expect(gp('path/+/foo')).toEqual('path/+'); + expect(gp('path/*/foo')).toEqual('path'); + expect(gp('path/@/foo')).toEqual('path/@'); + expect(gp('path/!/foo/')).toEqual('path/!/foo'); + expect(gp('path/?/foo/')).toEqual('path/?/foo'); + expect(gp('path/+/foo/')).toEqual('path/+/foo'); + expect(gp('path/*/foo/')).toEqual('path'); + expect(gp('path/@/foo/')).toEqual('path/@/foo'); + expect(gp('path/**/*')).toEqual('path'); + expect(gp('path/**/subdir/foo.*')).toEqual('path'); + expect(gp('path/subdir/**/foo.js')).toEqual('path/subdir'); + expect(gp('path/!subdir/foo.js')).toEqual('path/!subdir'); + expect(gp('path/{foo,bar}/')).toEqual('path'); + + done(); + }); + + it('should respect escaped characters', function (done) { + expect(gp('path/\\*\\*/subdir/foo.*')).toEqual('path/**/subdir'); + expect(gp('path/\\[\\*\\]/subdir/foo.*')).toEqual('path/[*]/subdir'); + expect(gp('path/\\*(a|b)/subdir/foo.*')).toEqual('path'); + expect(gp('path/\\*/(a|b)/subdir/foo.*')).toEqual('path/*'); + expect(gp('path/\\*\\(a\\|b\\)/subdir/foo.*')).toEqual( + 'path/*(a|b)/subdir' + ); + expect(gp('path/\\[foo bar\\]/subdir/foo.*')).toEqual( + 'path/[foo bar]/subdir' + ); + expect(gp('path/\\[bar]/')).toEqual('path/[bar]'); + expect(gp('path/\\[bar]')).toEqual('path'); + expect(gp('[bar]')).toEqual('.'); + expect(gp('[bar]/')).toEqual('.'); + expect(gp('./\\[bar]')).toEqual('.'); + expect(gp('\\[bar]/')).toEqual('[bar]'); + expect(gp('\\!dir/*')).toEqual('!dir'); + expect(gp('[bar\\]/')).toEqual('.'); + expect(gp('path/foo \\[bar]/')).toEqual('path/foo [bar]'); + expect(gp('path/\\{foo,bar}/')).toEqual('path/{foo,bar}'); + expect(gp('\\{foo,bar}/')).toEqual('{foo,bar}'); + expect(gp('\\{foo,bar\\}/')).toEqual('{foo,bar}'); + expect(gp('{foo,bar\\}/')).toEqual('.'); if (isWin32) { // On Windows we are trying to flip backslashes foo-\\( → foo-/( - assert.equal(gp('foo-\\(bar\\).md'), 'foo-'); + expect(gp('foo-\\(bar\\).md')).toEqual('foo-'); } else { - assert.equal(gp('foo-\\(bar\\).md'), '.'); - assert.equal(gp('\\[bar]'), '[bar]'); - assert.equal(gp('[bar\\]'), '.'); - assert.equal(gp('\\{foo,bar\\}'), '{foo,bar}'); - assert.equal(gp('{foo,bar\\}'), '.'); + expect(gp('foo-\\(bar\\).md')).toEqual('.'); + expect(gp('\\[bar]')).toEqual('.'); + expect(gp('[bar\\]')).toEqual('.'); + expect(gp('\\{foo,bar\\}')).toEqual('.'); + expect(gp('{foo,bar\\}')).toEqual('.'); } done(); }); - it('should respect glob enclosures with embedded separators', function(done) { - assert.equal(gp('path/{,/,bar/baz,qux}/'), 'path'); - assert.equal(gp('path/\\{,/,bar/baz,qux}/'), 'path/{,/,bar/baz,qux}'); - assert.equal(gp('path/\\{,/,bar/baz,qux\\}/'), 'path/{,/,bar/baz,qux}'); - assert.equal(gp('/{,/,bar/baz,qux}/'), '/'); - assert.equal(gp('/\\{,/,bar/baz,qux}/'), '/{,/,bar/baz,qux}'); - assert.equal(gp('{,/,bar/baz,qux}'), '.'); - assert.equal(gp('\\{,/,bar/baz,qux\\}'), '{,/,bar/baz,qux}'); - assert.equal(gp('\\{,/,bar/baz,qux}/'), '{,/,bar/baz,qux}'); - assert.equal(gp('path/foo[a\\\/]/'), 'path'); - assert.equal(gp('path/foo\\[a\\\/]/'), 'path/foo[a\\\/]'); - assert.equal(gp('foo[a\\\/]'), '.'); - assert.equal(gp('foo\\[a\\\/]'), 'foo[a\\\/]'); - assert.equal(gp('path/(foo/bar|baz)'), 'path'); - assert.equal(gp('path/(foo/bar|baz)/'), 'path'); - assert.equal(gp('path/\\(foo/bar|baz)/'), 'path/(foo/bar|baz)'); + it('should respect glob enclosures with embedded separators', function (done) { + /* eslint-disable no-useless-escape */ + expect(gp('path/{,/,bar/baz,qux}/')).toEqual('path'); + expect(gp('path/\\{,/,bar/baz,qux}/')).toEqual('path/{,/,bar/baz,qux}'); + expect(gp('path/\\{,/,bar/baz,qux\\}/')).toEqual('path/{,/,bar/baz,qux}'); + expect(gp('/{,/,bar/baz,qux}/')).toEqual('/'); + expect(gp('/\\{,/,bar/baz,qux}/')).toEqual('/{,/,bar/baz,qux}'); + expect(gp('{,/,bar/baz,qux}')).toEqual('.'); + expect(gp('\\{,/,bar/baz,qux\\}')).toEqual('{,/,bar/baz,qux}'); + expect(gp('\\{,/,bar/baz,qux}/')).toEqual('{,/,bar/baz,qux}'); + expect(gp('path/foo[a\\/]/')).toEqual('path'); + expect(gp('path/foo\\[a\\/]/')).toEqual('path/foo[a\\/]'); + expect(gp('foo[a\\/]')).toEqual('.'); + expect(gp('foo\\[a\\/]')).toEqual('foo[a\\/]'); + expect(gp('path/(foo/bar|baz)')).toEqual('path'); + expect(gp('path/(foo/bar|baz)/')).toEqual('path'); + expect(gp('path/\\(foo/bar|baz)/')).toEqual('path/(foo/bar|baz)'); + /* eslint-enable no-useless-escape */ done(); }); - it('should handle nested braces', function(done) { - assert.equal(gp('path/{../,./,{bar,/baz\\},qux\\}/'), 'path'); - assert.equal(gp('path/{../,./,\\{bar,/baz},qux}/'), 'path'); - assert.equal(gp('path/\\{../,./,\\{bar,/baz\\},qux\\}/'), 'path/{../,./,{bar,/baz},qux}'); - assert.equal(gp('{../,./,{bar,/baz\\},qux\\}/'), '.'); - assert.equal(gp('{../,./,{bar,/baz\\},qux\\}'), '.'); - assert.equal(gp('path/{,/,bar/{baz,qux\\}}/'), 'path'); - assert.equal(gp('path/{,/,bar/{baz,qux}\\}/'), 'path'); - // assert.equal(gp('path/\\{../,./,{bar,/baz},qux}/'), 'path'); + it('should handle nested braces', function (done) { + expect(gp('path/{../,./,{bar,/baz\\},qux\\}/')).toEqual('path'); + expect(gp('path/{../,./,\\{bar,/baz},qux}/')).toEqual('path'); + expect(gp('path/\\{../,./,\\{bar,/baz\\},qux\\}/')).toEqual( + 'path/{../,./,{bar,/baz},qux}' + ); + expect(gp('{../,./,{bar,/baz\\},qux\\}/')).toEqual('.'); + expect(gp('{../,./,{bar,/baz\\},qux\\}')).toEqual('.'); + expect(gp('path/{,/,bar/{baz,qux\\}}/')).toEqual('path'); + expect(gp('path/{,/,bar/{baz,qux}\\}/')).toEqual('path'); + // expect(gp('path/\\{../,./,{bar,/baz},qux}/')).toEqual('path'); done(); }); - it('should return parent dirname from non-glob paths', function(done) { - assert.equal(gp('path'), '.'); - assert.equal(gp('path/foo'), 'path'); - assert.equal(gp('path/foo/'), 'path/foo'); - assert.equal(gp('path/foo/bar.js'), 'path/foo'); + it('should return parent dirname from non-glob paths', function (done) { + expect(gp('path')).toEqual('.'); + expect(gp('path/foo')).toEqual('path'); + expect(gp('path/foo/')).toEqual('path/foo'); + expect(gp('path/foo/bar.js')).toEqual('path/foo'); done(); }); - it('should respect disabled auto flip backslashes', function(done) { - assert.equal(gp('foo-\\(bar\\).md', { flipBackslashes: false }), '.'); + it('should respect disabled auto flip backslashes', function (done) { + expect(gp('foo-\\(bar\\).md', { flipBackslashes: false })).toEqual('.'); done(); }); }); -describe('glob2base test patterns', function() { - it('should get a base name', function(done) { - assert.equal(gp('js/*.js'), 'js'); +describe('glob2base test patterns', function () { + it('should get a base name', function (done) { + expect(gp('js/*.js')).toEqual('js'); done(); }); - it('should get a base name from a nested glob', function(done) { - assert.equal(gp('js/**/test/*.js'), 'js'); + it('should get a base name from a nested glob', function (done) { + expect(gp('js/**/test/*.js')).toEqual('js'); done(); }); - it('should get a base name from a flat file', function(done) { - assert.equal(gp('js/test/wow.js'), 'js/test'); - assert.equal(gp('js/test/wow.js'), 'js/test'); + it('should get a base name from a flat file', function (done) { + expect(gp('js/test/wow.js')).toEqual('js/test'); + expect(gp('js/test/wow.js')).toEqual('js/test'); done(); }); - it('should get a base name from character class pattern', function(done) { - assert.equal(gp('js/t[a-z]st}/*.js'), 'js'); + it('should get a base name from character class pattern', function (done) { + expect(gp('js/t[a-z]st}/*.js')).toEqual('js'); done(); }); - it('should get a base name from brace , expansion', function(done) { - assert.equal(gp('js/{src,test}/*.js'), 'js'); + it('should get a base name from brace , expansion', function (done) { + expect(gp('js/{src,test}/*.js')).toEqual('js'); done(); }); - it('should get a base name from brace .. expansion', function(done) { - assert.equal(gp('js/test{0..9}/*.js'), 'js'); + it('should get a base name from brace .. expansion', function (done) { + expect(gp('js/test{0..9}/*.js')).toEqual('js'); done(); }); - it('should get a base name from extglob', function(done) { - assert.equal(gp('js/t+(wo|est)/*.js'), 'js'); + it('should get a base name from extglob', function (done) { + expect(gp('js/t+(wo|est)/*.js')).toEqual('js'); done(); }); - it('should get a base name from a path with non-exglob parens', function(done) { - assert.equal(gp('js/t(wo|est)/*.js'), 'js'); - assert.equal(gp('js/t/(wo|est)/*.js'), 'js/t'); + it('should get a base name from a path with non-exglob parens', function (done) { + expect(gp('js/t(wo|est)/*.js')).toEqual('js'); + expect(gp('js/t/(wo|est)/*.js')).toEqual('js/t'); done(); }); - it('should get a base name from a complex brace glob', function(done) { - assert.equal(gp('lib/{components,pages}/**/{test,another}/*.txt'), 'lib'); + it('should get a base name from a complex brace glob', function (done) { + expect(gp('lib/{components,pages}/**/{test,another}/*.txt')).toEqual('lib'); - assert.equal(gp('js/test/**/{images,components}/*.js'), 'js/test'); + expect(gp('js/test/**/{images,components}/*.js')).toEqual('js/test'); - assert.equal(gp('ooga/{booga,sooga}/**/dooga/{eooga,fooga}'), 'ooga'); + expect(gp('ooga/{booga,sooga}/**/dooga/{eooga,fooga}')).toEqual('ooga'); done(); }); - it('should not be susceptible to SNYK-JS-GLOBPARENT-1016905', function(done) { + it('should not be susceptible to SNYK-JS-GLOBPARENT-1016905', function (done) { // This will time out if susceptible. gp('{' + '/'.repeat(5000)); @@ -219,9 +227,9 @@ describe('glob2base test patterns', function() { }); if (isWin32) { - describe('technically invalid windows globs', function() { - it('should manage simple globs with backslash path separator', function(done) { - assert.equal(gp('C:\\path\\*.js'), 'C:/path'); + describe('technically invalid windows globs', function () { + it('should manage simple globs with backslash path separator', function (done) { + expect(gp('C:\\path\\*.js')).toEqual('C:/path'); done(); });