From cfeaa2933c8ed0931f37a44936a8e2bf22a0ba40 Mon Sep 17 00:00:00 2001 From: jonschlinkert Date: Sun, 28 May 2017 20:03:25 -0400 Subject: [PATCH] docs --- .verb.md | 253 ++++++++++---- CHANGELOG.md | 37 ++ README.md | 567 +++++++++++++++++++++---------- appveyor.yml | 2 +- docs/minimatch.md | 214 ------------ docs/switching-from-minimatch.md | 28 -- 6 files changed, 611 insertions(+), 490 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 docs/minimatch.md delete mode 100644 docs/switching-from-minimatch.md diff --git a/.verb.md b/.verb.md index e9a45e06..88d4fd9d 100644 --- a/.verb.md +++ b/.verb.md @@ -19,9 +19,9 @@ console.log(mm.isMatch('foo', 'f*')); // true **Switching from [minimatch](#switching-from-minimatch) and [multimatch](#switching-from-multimatch) is easy**: -* [mm()](#usage) is the same as [multimatch()][multimatch] -* [mm.match()](#match) is the same as [minimatch.match()][minimatch] -* use [mm.isMatch()](#ismatch) instead of [minimatch()][minimatch] +* use [mm.isMatch()](#ismatch) instead of `minimatch()` +* [mm.match()](#match) is the same as `minimatch.match()` +* [mm()](#usage) is the same as `multimatch()` **Heads up!** @@ -31,18 +31,29 @@ There is one notable difference between micromatch and minimatch in regards to h > micromatch is a [drop-in replacement][switch] for minimatch and multimatch -Micromatch is [safer][braces]{#braces-is-safe}, [faster](#benchmarks), more accurate, and supports all of the same matching features as [minimatch][] and [multimatch][]. +**Speed and accuracy** -Moreover, micromatch has: +Micromatch uses [snapdragon][] for parsing and compiling globs, which results in: + +- Granular control over the entire conversion process in a way that is easy to understand, reason about, and customize. +- Faster matching, from a combination of optimized glob patterns and (optional) caching. +- Much greater accuracy than minimatch. In fact, nanomatch passes _all of the spec tests_ from bash, including some that bash still fails. However, since there is no real specification for globs, if you encounter a pattern that yields unexpected match results [after researching previous issues](../../issues), [please let us know](../../issues/new). + + +- [Micromatch is safer](https://github.com/jonschlinkert/braces#braces-is-safe), and is not subject to DoS with brace patterns, like minimatch and multimatch. +- [faster](#benchmarks) matching +- More accurate, with more than 36,000 [unit tests](./test) - and thousands more patterns tested - to prove it. _(minimatch and multimatch fail a great number of the tests)_. +- More complete support for the Bash 4.3 specification than minimatch and multimatch +- More reliable windows support than minimatch and multimatch +- Supports all of the same matching features as [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github.com/sindresorhus/multimatch) +- Micromatch uses real parsers and compilers. Although edge cases are inevitable, micromatch is better equipped to handle them. -* Better support for the Bash 4.3 specification than minimatch and multimatch -* Better windows support than minimatch and multimatch -* More than 36,000 [unit tests](./test), with thousands more patterns tested (minimatch and multimatch fail a great number of the tests) ### Features * Native support for multiple glob patterns (no need for wrappers like multimatch) -* Glob pattern support (`**/*`, `a/b/*.js`, or `['a/*.js', '!b.js']`) +* Basic wildcard support (`**/*`, `a/b/*.js`, or `['a/*.js', '*b.js']`) +* Negation support (`['!a/*.js', '*!(b).js']`) * [extglob][] support (`+(x|y)`, `!(a|b)`, etc) * [POSIX character class][brackets] support (`**/[[:alpha:][:digit:]]/`) * [brace expansion][braces] support (`a/b-{1..5}.md`, `one/{two,three}/four.md`) @@ -86,32 +97,34 @@ mm(['foo', 'bar', 'baz'], ['f*', '*z']); ## API {%= apidocs("index.js") %} - - ## Options -- [options.basename](#options-basename) -- [options.cache](#options-cache) -- [options.dot](#options-dot) -- [options.failglob](#options-failglob) -- [options.ignore](#options-ignore) -- [options.matchBase](#options-matchBase) -- [options.nobrace](#options-nobrace) -- [options.nocase](#options-nocase) -- [options.nodupes](#options-nodupes) -- [options.nonull](#options-nonull) -- [options.nullglob](#options-nullglob) -- [options.snapdragon](#options-snapdragon) -- [options.unescape](#options-unescape) -- [options.unixify](#options-unixify) +- [basename](#options-basename) +- [bash](#options-bash) +- [cache](#options-cache) +- [dot](#options-dot) +- [failglob](#options-failglob) +- [ignore](#options-ignore) +- [matchBase](#options-matchBase) +- [nobrace](#options-nobrace) +- [nocase](#options-nocase) +- [nodupes](#options-nodupes) +- [noext](#options-noext) +- [noglobstar](#options-noglobstar) +- [nonull](#options-nonull) +- [nullglob](#options-nullglob) +- [snapdragon](#options-snapdragon) +- [sourcemap](#options-sourcemap) +- [unescape](#options-unescape) +- [unixify](#options-unixify) ### options.basename Allow glob patterns without slashes to match a file path based on its basename. Same behavior as [minimatch][] option `matchBase`. -Type: `Boolean` +**Type**: `Boolean` -Default: `false` +**Default**: `false` **Example** @@ -123,40 +136,58 @@ mm(['a/b.js', 'a/c.md'], '*.js', {matchBase: true}); //=> ['a/b.js'] ``` +### options.bash + +Enabled by default, this option enforces bash-like behavior with stars immediately following a bracket expression. Bash bracket expressions are similar to regex character classes, but unlike regex, a star following a bracket expression **does not repeat the bracketed characters**. Instead, the star is treated the same as an other star. + +**Type**: `Boolean` + +**Default**: `true` + +**Example** + +```js +var files = ['abc', 'ajz']; +console.log(mm(files, '[a-c]*')); +//=> ['abc', 'ajz'] + +console.log(mm(files, '[a-c]*', {bash: false})); +``` + ### options.cache Disable regex and function memoization. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.dot Match dotfiles. Same behavior as [minimatch][] option `dot`. -Type: `Boolean` +**Type**: `Boolean` -Default: `false` +**Default**: `false` ### options.failglob Similar to the `--failglob` behavior in Bash, throws an error when no matches are found. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.ignore String or array of glob patterns to match files to ignore. -Type: `String|Array` +**Type**: `String|Array` -Default: `undefined` +**Default**: `undefined` ### options.matchBase @@ -168,9 +199,9 @@ Alias for [options.basename](#options-basename). Disable expansion of brace patterns. Same behavior as [minimatch][] option `nobrace`. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` See [braces][] for more information about extended brace expansion. @@ -179,18 +210,18 @@ See [braces][] for more information about extended brace expansion. Use a case-insensitive regex for matching files. Same behavior as [minimatch][]. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.nodupes Remove duplicate elements from the result array. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` **Example** @@ -204,15 +235,50 @@ mm.match(['a/b/c', 'a/b/c'], 'a/b/c', {nodupes: true}); //=> ['abc'] ``` +### options.noext + +Disable extglob support, so that extglobs are regarded as literal characters. + +**Type**: `Boolean` + +**Default**: `undefined` + +**Examples** + +```js +mm(['a/z', 'a/b', 'a/!(z)'], 'a/!(z)'); +//=> ['a/b', 'a/!(z)'] + +mm(['a/z', 'a/b', 'a/!(z)'], 'a/!(z)', {noext: true}); +//=> ['a/!(z)'] (matches only as literal characters) +``` + + ### options.nonegate Disallow negation (`!`) patterns, and treat leading `!` as a literal character to match. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` +### options.noglobstar + +Disable matching with globstars (`**`). + +**Type**: `Boolean` + +**Default**: `undefined` + +```js +mm(['a/b', 'a/b/c', 'a/b/c/d'], 'a/**'); +//=> ['a/b', 'a/b/c', 'a/b/c/d'] + +mm(['a/b', 'a/b/c', 'a/b/c/d'], 'a/**', {noglobstar: true}); +//=> ['a/b'] +``` + ### options.nonull Alias for [options.nullglob](#options-nullglob). @@ -222,27 +288,66 @@ Alias for [options.nullglob](#options-nullglob). If `true`, when no matches are found the actual (arrayified) glob pattern is returned instead of an empty array. Same behavior as [minimatch][] option `nonull`. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.snapdragon Pass your own instance of [snapdragon][], to customize parsers or compilers. -Type: `Object` +**Type**: `Object` + +**Default**: `undefined` + -Default: `undefined` +### options.sourcemap +Generate a source map by enabling the `sourcemap` option with the `.parse`, `.compile`, or `.create` methods. + +_(Note that sourcemaps are currently not enabled for brace patterns)_ + +**Examples** + +``` js +var mm = require('micromatch'); +var pattern = '*(*(of*(a)x)z)'; + +var res = mm.create('abc/*.js', {sourcemap: true}); +console.log(res.map); +// { version: 3, +// sources: [ 'string' ], +// names: [], +// mappings: 'AAAA,GAAG,EAAC,iBAAC,EAAC,EAAE', +// sourcesContent: [ 'abc/*.js' ] } + +var ast = mm.parse('abc/**/*.js'); +var res = mm.compile(ast, {sourcemap: true}); +console.log(res.map); +// { version: 3, +// sources: [ 'string' ], +// names: [], +// mappings: 'AAAA,GAAG,EAAC,2BAAE,EAAC,iBAAC,EAAC,EAAE', +// sourcesContent: [ 'abc/**/*.js' ] } + +var ast = mm.parse(pattern); +var res = mm.compile(ast, {sourcemap: true}); +console.log(res.map); +// { version: 3, +// sources: [ 'string' ], +// names: [], +// mappings: 'AAAA,CAAE,CAAE,EAAE,CAAE,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC', +// sourcesContent: [ '*(*(of*(a)x)z)' ] } +``` ### options.unescape Remove backslashes from returned matches. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` **Example** @@ -260,9 +365,9 @@ mm.match(['abc', 'a\\*c'], 'a\\*c', {unescape: true}); Convert path separators on returned files to posix/unix-style forward slashes. -Type: `Boolean` +**Type**: `Boolean` -Default: `true` +**Default**: `true` on windows, `false` everywhere else **Example** @@ -284,18 +389,16 @@ Extended globbing, as described by the bash man page: | **pattern** | **regex equivalent** | **description** | | --- | --- | --- | -| `?(pattern-list)` | `(... | ...)?` | Matches zero or one occurrence of the given patterns | -| `*(pattern-list)` | `(... | ...)*` | Matches zero or more occurrences of the given patterns | -| `+(pattern-list)` | `(... | ...)+` | Matches one or more occurrences of the given patterns | -| `@(pattern-list)` | `(... | ...)` * | Matches one of the given patterns | -| `!(pattern-list)` | N/A | Matches anything except one of the given patterns | +| `?(pattern-list)` | `(foo|bar)?` | Matches zero or one occurrence of the given patterns | +| `*(pattern-list)` | `(foo|bar)*` | Matches zero or more occurrences of the given patterns | +| `+(pattern-list)` | `(foo|bar)+` | Matches one or more occurrences of the given patterns | +| `@(pattern-list)` | `(foo|bar)` * | Matches one of the given patterns | +| `!(pattern-list)` | N/A (equivalent regex is much more complicated) | Matches anything except one of the given patterns | -* `@` isn't a RegEx character. +* Note that `@` isn't a RegEx character. Powered by [extglob](https://github.com/jonschlinkert/extglob). Visit that library for the full range of options or to report extglob related issues. -See [extglob](https://github.com/jonschlinkert/extglob) for more information about extended globs. - ### braces **Expanded braces** @@ -309,7 +412,7 @@ Braces are expanded when `` By default, brace patterns work the same way regex logical `OR` operators. For example, `(a|b)` will achieve the same result as `{a,b}`. -Visit [braces](https://github.com/jonschlinkert/braces) to ask questions and create an issue related to brace-expansion, or to see the full range of features and options related to brace expansion. +Visit [braces](https://github.com/jonschlinkert/braces) to see the full range of features and options related to brace expansion, or to create brace matching or expansion related issues. ### regex character classes @@ -330,26 +433,34 @@ Given `['a.js', 'b.js', 'c.js', 'd.js', 'E.js']`: * `(b|d).js`: would match either `b` or `d`, returning `['b.js', 'd.js']` * `(b|[A-Z]).js`: would match either `b` or an uppercase letter, returning `['b.js', 'E.js']` -As with regex, parenthese can be nested, so patterns like `((a|b)|c)/b` will work. But it might be easier to achieve your goal using brace expansion. +As with regex, parens can be nested, so patterns like `((a|b)|c)/b` will work. Although brace expansion might be friendlier to use, depending on preference. ### POSIX bracket expressions +POSIX brackets are intended to be more user-friendly than regex character classes. This of course is in the eye of the beholder. + **Example** ```js mm.isMatch('a1', '[[:alpha:][:digit:]]'); //=> true + +mm.isMatch('a1', '[[:alpha:][:alpha:]]'); +//=> false ``` See [expand-brackets](https://github.com/jonschlinkert/expand-brackets) for more information about bracket expressions. *** + ## Notes ### Bash 4.3 parity -Whenever possible parsing behavior for patterns is based on globbing specifications in Bash 4.3, which is mostly also constistent with minimatch. Patterns that aren't described in enough detail by the Bash spec follow wildmatch spec (used by git). +Whenever possible matching behavior is based on behavior Bash 4.3, which is mostly consistent with minimatch. + +However, it's suprising how many edge cases and rabbit holes there are with glob matching, and since there is no real glob specification, and micromatch is more accurate than both Bash and minimatch, there are cases where best-guesses were made for behavior. In a few cases where Bash had no answers, we used wildmatch (used by git) as a fallback. ### Backslashes @@ -365,21 +476,21 @@ We made this decision for micromatch for a couple of reasons: **A note about joining paths to globs** -Note that when you pass something like `path.join('foo', '*')` to micromatch, you are creating a filepath and expecting it to still work as a glob pattern. This causes problems on windows, since the node.js `path` module converts `/` to `\\` and/or uses `\\` as the path separator when joining paths. - -In other words, since `\\` is reserved as an escape character in globs, on windows `path.join('foo', '*')` would result in `foo\\*`, which tells micromatch to match `*` as a literal character (fwiw this is the same behavior as bash). - - - -This is the convention in all mainstream globbing libs, including bash glob, minimatch and node-glob (although some users are [confused about how this works](https://github.com/isaacs/node-glob/issues/212) +Note that when you pass something like `path.join('foo', '*')` to micromatch, you are creating a filepath and expecting it to still work as a glob pattern. This causes problems on windows, since the `path.sep` is `\\`. +In other words, since `\\` is reserved as an escape character in globs, on windows `path.join('foo', '*')` would result in `foo\\*`, which tells micromatch to match `*` as a literal character. This is the same behavior as bash. +## Contributing -, and minimatch enforces this convention by converting backslashes to forward slashes). +All contributions are welcome! Please read [the contributing guide](.github/contributing.md) to get started. +**A special note about bug reports** +Please feel free to create an issue if you find something that you think isn't right. However, especially (but not exclusively) if you find a matching-related issue, please please try do the following first: -To get around this, you can either do the joining manually or find a lib on npm that does this. +- research existing issues first +- visit the [GNU Bash documentation](https://www.gnu.org/software/bash/manual/) to see how Bash deals with the pattern +- visit the [minimatch][] documentation to cross-check expected behavior ## Benchmarks diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..6ba17ef9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,37 @@ +## History + +### key + +Changelog entries are classified using the following labels _(from [keep-a-changelog][]_): + +- `added`: for new features +- `changed`: for changes in existing functionality +- `deprecated`: for once-stable features removed in upcoming releases +- `removed`: for deprecated features removed in this release +- `fixed`: for any bug fixes +- `bumped`: updated dependencies, only minor or higher will be listed. + +### [3.0.0] - 2017-04-11 + +TODO + +### [1.0.1] - 2016-12-12 + +**Added** + +- Support for windows path edge cases where backslashes are used in brackets or other unusual combinations. + +### [1.0.0] - 2016-12-12 + +Stable release. + +### [0.1.0] - 2016-10-08 + +First release. + + +[Unreleased]: https://github.com/jonschlinkert/micromatch/compare/0.1.0...HEAD +[0.2.0]: https://github.com/jonschlinkert/micromatch/compare/0.1.0...0.2.0 + +[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog + diff --git a/README.md b/README.md index c6e3ab0c..2f731f9f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# micromatch [![NPM version](https://img.shields.io/npm/v/micromatch.svg?style=flat)](https://www.npmjs.com/package/micromatch) [![NPM monthly downloads](https://img.shields.io/npm/dm/micromatch.svg?style=flat)](https://npmjs.org/package/micromatch) [![NPM total downloads](https://img.shields.io/npm/dt/micromatch.svg?style=flat)](https://npmjs.org/package/micromatch) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/micromatch.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/micromatch) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/micromatch.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/micromatch) +# micromatch [![NPM version](https://img.shields.io/npm/v/micromatch.svg?style=flat)](https://www.npmjs.com/package/micromatch) [![NPM monthly downloads](https://img.shields.io/npm/dm/micromatch.svg?style=flat)](https://npmjs.org/package/micromatch) [![NPM total downloads](https://img.shields.io/npm/dt/micromatch.svg?style=flat)](https://npmjs.org/package/micromatch) [![Linux Build Status](https://img.shields.io/travis/micromatch/micromatch.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/micromatch) [![Windows Build Status](https://img.shields.io/appveyor/ci/micromatch/micromatch.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/micromatch/micromatch) > Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. @@ -13,6 +13,7 @@ - [API](#api) - [Options](#options) * [options.basename](#optionsbasename) + * [options.bash](#optionsbash) * [options.cache](#optionscache) * [options.dot](#optionsdot) * [options.failglob](#optionsfailglob) @@ -21,10 +22,13 @@ * [options.nobrace](#optionsnobrace) * [options.nocase](#optionsnocase) * [options.nodupes](#optionsnodupes) + * [options.noext](#optionsnoext) * [options.nonegate](#optionsnonegate) + * [options.noglobstar](#optionsnoglobstar) * [options.nonull](#optionsnonull) * [options.nullglob](#optionsnullglob) * [options.snapdragon](#optionssnapdragon) + * [options.sourcemap](#optionssourcemap) * [options.unescape](#optionsunescape) * [options.unixify](#optionsunixify) - [Extended globbing](#extended-globbing) @@ -34,18 +38,13 @@ * [regex groups](#regex-groups) * [POSIX bracket expressions](#posix-bracket-expressions) - [Notes](#notes) + * [Bash 4.3 parity](#bash-43-parity) + * [Backslashes](#backslashes) +- [Contributing](#contributing) - [Benchmarks](#benchmarks) * [Running benchmarks](#running-benchmarks) * [Latest results](#latest-results) - [About](#about) - * [Related projects](#related-projects) - * [Contributing](#contributing) - * [Contributors](#contributors) - * [Release history](#release-history) - * [Building docs](#building-docs) - * [Running tests](#running-tests) - * [Author](#author) - * [License](#license) _(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_ @@ -78,26 +77,38 @@ console.log(mm.isMatch('foo', 'f*')); // true **Switching from [minimatch](#switching-from-minimatch) and [multimatch](#switching-from-multimatch) is easy**: -* [mm()](#usage) is the same as [multimatch()](https://github.com/sindresorhus/multimatch) -* [mm.match()](#match) is the same as [minimatch.match()](https://github.com/isaacs/minimatch) -* use [mm.isMatch()](#ismatch) instead of [minimatch()](https://github.com/isaacs/minimatch) +* use [mm.isMatch()](#ismatch) instead of `minimatch()` +* [mm.match()](#match) is the same as `minimatch.match()` +* [mm()](#usage) is the same as `multimatch()` + +**Heads up!** + +There is one notable difference between micromatch and minimatch in regards to how backslashes are handled. See [the notes about backslashes](#backslashes) for more information. ## Why use micromatch? > micromatch is a [drop-in replacement](#switch-from-minimatch) for minimatch and multimatch -Micromatch is [safer](https://github.com/jonschlinkert/braces#braces-is-safe), [faster](#benchmarks), more accurate, and supports all of the same matching features as [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github.com/sindresorhus/multimatch). +**Speed and accuracy** -Moreover, micromatch has: +Micromatch uses [snapdragon](https://github.com/jonschlinkert/snapdragon) for parsing and compiling globs, which results in: -* Better support for the Bash 4.3 specification than minimatch and multimatch -* Better windows support than minimatch and multimatch -* More than 36,000 [unit tests](./test), with thousands more patterns tested (minimatch and multimatch fail a great number of the tests) +* Granular control over the entire conversion process in a way that is easy to understand, reason about, and customize. +* Faster matching, from a combination of optimized glob patterns and (optional) caching. +* Much greater accuracy than minimatch. In fact, nanomatch passes _all of the spec tests_ from bash, including some that bash still fails. However, since there is no real specification for globs, if you encounter a pattern that yields unexpected match results [after researching previous issues](../../issues), [please let us know](../../issues/new). +* [Micromatch is safer](https://github.com/jonschlinkert/braces#braces-is-safe), and is not subject to DoS with brace patterns, like minimatch and multimatch. +* [faster](#benchmarks) matching +* More accurate, with more than 36,000 [unit tests](./test) - and thousands more patterns tested - to prove it. _(minimatch and multimatch fail a great number of the tests)_. +* More complete support for the Bash 4.3 specification than minimatch and multimatch +* More reliable windows support than minimatch and multimatch +* Supports all of the same matching features as [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github.com/sindresorhus/multimatch) +* Micromatch uses real parsers and compilers. Although edge cases are inevitable, micromatch is better equipped to handle them. ### Features * Native support for multiple glob patterns (no need for wrappers like multimatch) -* Glob pattern support (`**/*`, `a/b/*.js`, or `['a/*.js', '!b.js']`) +* Basic wildcard support (`**/*`, `a/b/*.js`, or `['a/*.js', '*b.js']`) +* Negation support (`['!a/*.js', '*!(b).js']`) * [extglob](https://github.com/jonschlinkert/extglob) support (`+(x|y)`, `!(a|b)`, etc) * [POSIX character class](https://github.com/jonschlinkert/expand-brackets) support (`**/[[:alpha:][:digit:]]/`) * [brace expansion](https://github.com/jonschlinkert/braces) support (`a/b-{1..5}.md`, `one/{two,three}/four.md`) @@ -140,10 +151,17 @@ mm(['foo', 'bar', 'baz'], ['f*', '*z']); ## API -### [micromatch](index.js#L40) +### [micromatch](index.js#L41) The main function takes a list of strings and one or more glob patterns to use for matching. +**Params** + +* `list` **{Array}**: A list of strings to match +* `patterns` **{String|Array}**: One or more glob patterns to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Array}**: Returns an array of matches + **Example** ```js @@ -154,16 +172,16 @@ console.log(mm(['a.js', 'a.txt'], ['*.js'])); //=> [ 'a.js' ] ``` -**Params** +### [.match](index.js#L107) -* `list` **{Array}**: A list of strings to match -* `patterns` **{String|Array}**: One or more glob patterns to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed -* `returns` **{Array}**: Returns an array of matches +Similar to the main function, but `pattern` must be a string. -### [.match](index.js#L103) +**Params** -Similar to the main function, but `pattern` must be a string. +* `list` **{Array}**: Array of strings to match +* `pattern` **{String}**: Glob pattern to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Array}**: Returns an array of matches **Example** @@ -175,16 +193,16 @@ console.log(mm.match(['a.a', 'a.aa', 'a.b', 'a.c'], '*.a')); //=> ['a.a', 'a.aa'] ``` -**Params** +### [.isMatch](index.js#L168) -* `list` **{Array}**: Array of strings to match -* `pattern` **{String}**: Glob pattern to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed -* `returns` **{Array}**: Returns an array of matches +Returns true if the specified `string` matches the given glob `pattern`. -### [.isMatch](index.js#L166) +**Params** -Returns true if the specified `string` matches the given glob `pattern`. +* `string` **{String}**: String to match +* `pattern` **{String}**: Glob pattern to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Boolean}**: Returns true if the string matches the glob pattern. **Example** @@ -198,37 +216,66 @@ console.log(mm.isMatch('a.b', '*.a')); //=> false ``` -**Params** +### [.some](index.js#L206) -* `string` **{String}**: String to match -* `pattern` **{String}**: Glob pattern to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed -* `returns` **{Boolean}**: Returns true if the string matches the glob pattern. +Returns true if some of the elements in the given `list` match any of the given glob `patterns`. -### [.not](index.js#L200) +**Params** -Returns a list of strings that _DO NOT MATCH_ any of the given `patterns`. +* `list` **{String|Array}**: The string or array of strings to test. Returns as soon as the first match is found. +* `patterns` **{String|Array}**: One or more glob patterns to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Boolean}**: Returns true if any patterns match `str` **Example** ```js var mm = require('micromatch'); -mm.not(list, patterns[, options]); +mm.some(list, patterns[, options]); -console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); -//=> ['b.b', 'c.c'] +console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); +// true +console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); +// false ``` +### [.every](index.js#L244) + +Returns true if every element in the given `list` matches at least one of the given glob `patterns`. + **Params** -* `list` **{Array}**: Array of strings to match. -* `patterns` **{String|Array}**: One or more glob pattern to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed -* `returns` **{Array}**: Returns an array of strings that **do not match** the given patterns. +* `list` **{String|Array}**: The string or array of strings to test. +* `patterns` **{String|Array}**: One or more glob patterns to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Boolean}**: Returns true if any patterns match `str` -### [.any](index.js#L237) +**Example** -Returns true if the given `string` matches any of the given glob `patterns`. +```js +var mm = require('micromatch'); +mm.every(list, patterns[, options]); + +console.log(mm.every('foo.js', ['foo.js'])); +// true +console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); +// true +console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); +// false +console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); +// false +``` + +### [.any](index.js#L278) + +Returns true if **any** of the given glob `patterns` match the specified `string`. + +**Params** + +* `str` **{String|Array}**: The string to test. +* `patterns` **{String|Array}**: One or more glob patterns to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Boolean}**: Returns true if any patterns match `str` **Example** @@ -242,17 +289,68 @@ console.log(mm.any('a.a', 'b.*')); //=> false ``` +### [.all](index.js#L326) + +Returns true if **all** of the given `patterns` match the specified string. + **Params** -* `list` **{String|Array}**: The string or array of strings to test. Returns as soon as the first match is found. +* `str` **{String|Array}**: The string to test. * `patterns` **{String|Array}**: One or more glob patterns to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed +* `options` **{Object}**: See available [options](#options) for changing how matches are performed * `returns` **{Boolean}**: Returns true if any patterns match `str` -### [.contains](index.js#L280) +**Example** + +```js +var mm = require('micromatch'); +mm.all(string, patterns[, options]); + +console.log(mm.all('foo.js', ['foo.js'])); +// true + +console.log(mm.all('foo.js', ['*.js', '!foo.js'])); +// false + +console.log(mm.all('foo.js', ['*.js', 'foo.js'])); +// true + +console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); +// true +``` + +### [.not](index.js#L360) + +Returns a list of strings that _**do not match any**_ of the given `patterns`. + +**Params** + +* `list` **{Array}**: Array of strings to match. +* `patterns` **{String|Array}**: One or more glob pattern to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Array}**: Returns an array of strings that **do not match** the given patterns. + +**Example** + +```js +var mm = require('micromatch'); +mm.not(list, patterns[, options]); + +console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); +//=> ['b.b', 'c.c'] +``` + +### [.contains](index.js#L395) Returns true if the given `string` contains the given pattern. Similar to [.isMatch](#isMatch) but the pattern can match any part of the string. +**Params** + +* `str` **{String}**: The string to match. +* `patterns` **{String|Array}**: Glob pattern to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Boolean}**: Returns true if the patter matches any part of `str`. + **Example** ```js @@ -265,16 +363,16 @@ console.log(mm.contains('aa/bb/cc', '*d')); //=> false ``` -**Params** +### [.matchKeys](index.js#L451) -* `str` **{String}**: The string to match. -* `pattern` **{String}**: Glob pattern to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed -* `returns` **{Boolean}**: Returns true if the patter matches any part of `str`. +Filter the keys of the given object with the given `glob` pattern and `options`. Does not attempt to match nested keys. If you need this feature, use [glob-object](https://github.com/jonschlinkert/glob-object) instead. -### [.matchKeys](index.js#L329) +**Params** -Filter the keys of the given object with the given `glob` pattern and `options`. Does not attempt to match nested keys. If you need this feature, use [glob-object](https://github.com/jonschlinkert/glob-object) instead. +* `object` **{Object}**: The object with keys to filter. +* `patterns` **{String|Array}**: One or more glob patterns to use for matching. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed +* `returns` **{Object}**: Returns an object with only keys that match the given patterns. **Example** @@ -287,16 +385,15 @@ console.log(mm.matchKeys(obj, '*b')); //=> { ab: 'b' } ``` -**Params** +### [.matcher](index.js#L480) -* `object` **{Object}**: The object with keys to filter. -* `patterns` **{String|Array}**: One or more glob patterns to use for matching. -* `options` **{Object}**: Any [options](#options) to change how matches are performed -* `returns` **{Object}**: Returns an object with only keys that match the given patterns. +Returns a memoized matcher function from the given glob `pattern` and `options`. The returned function takes a string to match as its only argument and returns true if the string is a match. -### [.matcher](index.js#L358) +**Params** -Returns a memoized matcher function from the given glob `pattern` and `options`. The returned function takes a string to match as its only argument and returns true if the string is a match. +* `pattern` **{String}**: Glob pattern +* `options` **{Object}**: See available [options](#options) for changing how matches are performed. +* `returns` **{Function}**: Returns a matcher function. **Example** @@ -311,15 +408,15 @@ console.log(isMatch('a.b')); //=> true ``` -**Params** +### [.makeRe](index.js#L554) -* `pattern` **{String}**: Glob pattern -* `options` **{Object}**: Any [options](#options) to change how matches are performed. -* `returns` **{Function}**: Returns a matcher function. +Create a regular expression from the given glob `pattern`. -### [.makeRe](index.js#L420) +**Params** -Create a regular expression from the given glob `pattern`. +* `pattern` **{String}**: A glob pattern to convert to regex. +* `options` **{Object}**: See available [options](#options) for changing how matches are performed. +* `returns` **{RegExp}**: Returns a regex created from the given pattern. **Example** @@ -331,15 +428,15 @@ console.log(mm.makeRe('*.js')); //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ ``` -**Params** +### [.braces](index.js#L601) -* `pattern` **{String}**: A glob pattern to convert to regex. -* `options` **{Object}**: Any [options](#options) to change how matches are performed. -* `returns` **{RegExp}**: Returns a regex created from the given pattern. +Expand the given brace `pattern`. -### [.braces](index.js#L463) +**Params** -Expand the given brace `pattern`. +* `pattern` **{String}**: String with brace pattern to expand. +* `options` **{Object}**: Any [options](#options) to change how expansion is performed. See the [braces](https://github.com/jonschlinkert/braces) library for all available options. +* `returns` **{Array}** **Example** @@ -352,15 +449,15 @@ console.log(mm.braces('foo/{a,b}/bar', {expand: true})); //=> ['foo/(a|b)/bar'] ``` -**Params** +### [.create](index.js#L665) -* `pattern` **{String}**: String with brace pattern to expand. -* `options` **{Object}**: Any [options](#options) to change how expansion is performed. See the [braces](https://github.com/jonschlinkert/braces) library for all available options. -* `returns` **{Array}** +Parses the given glob `pattern` and returns an array of abstract syntax trees (ASTs), with the compiled `output` and optional source `map` on each AST. -### [.create](index.js#L516) +**Params** -Parses the given glob `pattern` and returns an object with the compiled `output` and optional source `map`. +* `pattern` **{String}**: Glob pattern to parse and compile. +* `options` **{Object}**: Any [options](#options) to change how parsing and compiling is performed. +* `returns` **{Object}**: Returns an object with the parsed AST, compiled string and optional source map. **Example** @@ -369,7 +466,7 @@ var mm = require('micromatch'); mm.create(pattern[, options]); console.log(mm.create('abc/*.js')); -// { options: { source: 'string', sourcemap: true }, +// [{ options: { source: 'string', sourcemap: true }, // state: {}, // compilers: // { ... }, @@ -391,18 +488,18 @@ console.log(mm.create('abc/*.js')); // position: { line: 1, column: 28 }, // content: {}, // files: {}, -// idx: 6 } +// idx: 6 }] ``` -**Params** +### [.parse](index.js#L712) -* `pattern` **{String}**: Glob pattern to parse and compile. -* `options` **{Object}**: Any [options](#options) to change how parsing and compiling is performed. -* `returns` **{Object}**: Returns an object with the parsed AST, compiled string and optional source map. +Parse the given `str` with the given `options`. -### [.parse](index.js#L573) +**Params** -Parse the given `str` with the given `options`. +* `str` **{String}** +* `options` **{Object}** +* `returns` **{Object}**: Returns an AST **Example** @@ -427,15 +524,15 @@ console.log(ast); // { type: 'eos', val: '' } ] } ``` -**Params** +### [.compile](index.js#L765) -* `str` **{String}** -* `options` **{Object}** -* `returns` **{Object}**: Returns an AST +Compile the given `ast` or string with the given `options`. -### [.compile](index.js#L626) +**Params** -Compile the given `ast` or string with the given `options`. +* `ast` **{Object|String}** +* `options` **{Object}** +* `returns` **{Object}**: Returns an object that has an `output` property with the compiled string. **Example** @@ -461,13 +558,7 @@ console.log(mm.compile(ast)); // parsingErrors: [] } ``` -**Params** - -* `ast` **{Object|String}** -* `options` **{Object}** -* `returns` **{Object}**: Returns an object that has an `output` property with the compiled string. - -### [.clearCache](index.js#L649) +### [.clearCache](index.js#L786) Clear the regex cache. @@ -479,28 +570,32 @@ mm.clearCache(); ## Options -* [options.basename](#options-basename) -* [options.cache](#options-cache) -* [options.dot](#options-dot) -* [options.failglob](#options-failglob) -* [options.ignore](#options-ignore) -* [options.matchBase](#options-matchBase) -* [options.nobrace](#options-nobrace) -* [options.nocase](#options-nocase) -* [options.nodupes](#options-nodupes) -* [options.nonull](#options-nonull) -* [options.nullglob](#options-nullglob) -* [options.snapdragon](#options-snapdragon) -* [options.unescape](#options-unescape) -* [options.unixify](#options-unixify) +* [basename](#options-basename) +* [bash](#options-bash) +* [cache](#options-cache) +* [dot](#options-dot) +* [failglob](#options-failglob) +* [ignore](#options-ignore) +* [matchBase](#options-matchBase) +* [nobrace](#options-nobrace) +* [nocase](#options-nocase) +* [nodupes](#options-nodupes) +* [noext](#options-noext) +* [noglobstar](#options-noglobstar) +* [nonull](#options-nonull) +* [nullglob](#options-nullglob) +* [snapdragon](#options-snapdragon) +* [sourcemap](#options-sourcemap) +* [unescape](#options-unescape) +* [unixify](#options-unixify) ### options.basename Allow glob patterns without slashes to match a file path based on its basename. Same behavior as [minimatch](https://github.com/isaacs/minimatch) option `matchBase`. -Type: `Boolean` +**Type**: `Boolean` -Default: `false` +**Default**: `false` **Example** @@ -512,37 +607,55 @@ mm(['a/b.js', 'a/c.md'], '*.js', {matchBase: true}); //=> ['a/b.js'] ``` +### options.bash + +Enabled by default, this option enforces bash-like behavior with stars immediately following a bracket expression. Bash bracket expressions are similar to regex character classes, but unlike regex, a star following a bracket expression **does not repeat the bracketed characters**. Instead, the star is treated the same as an other star. + +**Type**: `Boolean` + +**Default**: `true` + +**Example** + +```js +var files = ['abc', 'ajz']; +console.log(mm(files, '[a-c]*')); +//=> ['abc', 'ajz'] + +console.log(mm(files, '[a-c]*', {bash: false})); +``` + ### options.cache Disable regex and function memoization. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.dot Match dotfiles. Same behavior as [minimatch](https://github.com/isaacs/minimatch) option `dot`. -Type: `Boolean` +**Type**: `Boolean` -Default: `false` +**Default**: `false` ### options.failglob Similar to the `--failglob` behavior in Bash, throws an error when no matches are found. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.ignore String or array of glob patterns to match files to ignore. -Type: `String|Array` +**Type**: `String|Array` -Default: `undefined` +**Default**: `undefined` ### options.matchBase @@ -552,9 +665,9 @@ Alias for [options.basename](#options-basename). Disable expansion of brace patterns. Same behavior as [minimatch](https://github.com/isaacs/minimatch) option `nobrace`. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` See [braces](https://github.com/jonschlinkert/braces) for more information about extended brace expansion. @@ -562,17 +675,17 @@ See [braces](https://github.com/jonschlinkert/braces) for more information about Use a case-insensitive regex for matching files. Same behavior as [minimatch](https://github.com/isaacs/minimatch). -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.nodupes Remove duplicate elements from the result array. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` **Example** @@ -586,13 +699,47 @@ mm.match(['a/b/c', 'a/b/c'], 'a/b/c', {nodupes: true}); //=> ['abc'] ``` +### options.noext + +Disable extglob support, so that extglobs are regarded as literal characters. + +**Type**: `Boolean` + +**Default**: `undefined` + +**Examples** + +```js +mm(['a/z', 'a/b', 'a/!(z)'], 'a/!(z)'); +//=> ['a/b', 'a/!(z)'] + +mm(['a/z', 'a/b', 'a/!(z)'], 'a/!(z)', {noext: true}); +//=> ['a/!(z)'] (matches only as literal characters) +``` + ### options.nonegate Disallow negation (`!`) patterns, and treat leading `!` as a literal character to match. -Type: `Boolean` +**Type**: `Boolean` + +**Default**: `undefined` + +### options.noglobstar -Default: `undefined` +Disable matching with globstars (`**`). + +**Type**: `Boolean` + +**Default**: `undefined` + +```js +mm(['a/b', 'a/b/c', 'a/b/c/d'], 'a/**'); +//=> ['a/b', 'a/b/c', 'a/b/c/d'] + +mm(['a/b', 'a/b/c', 'a/b/c/d'], 'a/**', {noglobstar: true}); +//=> ['a/b'] +``` ### options.nonull @@ -602,25 +749,64 @@ Alias for [options.nullglob](#options-nullglob). If `true`, when no matches are found the actual (arrayified) glob pattern is returned instead of an empty array. Same behavior as [minimatch](https://github.com/isaacs/minimatch) option `nonull`. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` ### options.snapdragon Pass your own instance of [snapdragon](https://github.com/jonschlinkert/snapdragon), to customize parsers or compilers. -Type: `Object` +**Type**: `Object` + +**Default**: `undefined` + +### options.sourcemap + +Generate a source map by enabling the `sourcemap` option with the `.parse`, `.compile`, or `.create` methods. + +_(Note that sourcemaps are currently not enabled for brace patterns)_ -Default: `undefined` +**Examples** + +``` js +var mm = require('micromatch'); +var pattern = '*(*(of*(a)x)z)'; + +var res = mm.create('abc/*.js', {sourcemap: true}); +console.log(res.map); +// { version: 3, +// sources: [ 'string' ], +// names: [], +// mappings: 'AAAA,GAAG,EAAC,iBAAC,EAAC,EAAE', +// sourcesContent: [ 'abc/*.js' ] } + +var ast = mm.parse('abc/**/*.js'); +var res = mm.compile(ast, {sourcemap: true}); +console.log(res.map); +// { version: 3, +// sources: [ 'string' ], +// names: [], +// mappings: 'AAAA,GAAG,EAAC,2BAAE,EAAC,iBAAC,EAAC,EAAE', +// sourcesContent: [ 'abc/**/*.js' ] } + +var ast = mm.parse(pattern); +var res = mm.compile(ast, {sourcemap: true}); +console.log(res.map); +// { version: 3, +// sources: [ 'string' ], +// names: [], +// mappings: 'AAAA,CAAE,CAAE,EAAE,CAAE,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC', +// sourcesContent: [ '*(*(of*(a)x)z)' ] } +``` ### options.unescape Remove backslashes from returned matches. -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` **Example** @@ -638,9 +824,9 @@ mm.match(['abc', 'a\\*c'], 'a\\*c', {unescape: true}); Convert path separators on returned files to posix/unix-style forward slashes. -Type: `Boolean` +**Type**: `Boolean` -Default: `true` +**Default**: `true` on windows, `false` everywhere else **Example** @@ -662,18 +848,16 @@ Extended globbing, as described by the bash man page: | **pattern** | **regex equivalent** | **description** | | --- | --- | --- | -| `?(pattern-list)` | `(... | ...)?` | Matches zero or one occurrence of the given patterns | -| `*(pattern-list)` | `(... | ...)*` | Matches zero or more occurrences of the given patterns | -| `+(pattern-list)` | `(... | ...)+` | Matches one or more occurrences of the given patterns | -| `@(pattern-list)` | `(... | ...)` * | Matches one of the given patterns | -| `!(pattern-list)` | N/A | Matches anything except one of the given patterns | +| `?(pattern-list)` | `(foo | bar)?` | Matches zero or one occurrence of the given patterns | +| `*(pattern-list)` | `(foo | bar)*` | Matches zero or more occurrences of the given patterns | +| `+(pattern-list)` | `(foo | bar)+` | Matches one or more occurrences of the given patterns | +| `@(pattern-list)` | `(foo | bar)` * | Matches one of the given patterns | +| `!(pattern-list)` | N/A (equivalent regex is much more complicated) | Matches anything except one of the given patterns | -* `@` isn't a RegEx character. +* Note that `@` isn't a RegEx character. Powered by [extglob](https://github.com/jonschlinkert/extglob). Visit that library for the full range of options or to report extglob related issues. -See [extglob](https://github.com/jonschlinkert/extglob) for more information about extended globs. - ### braces **Expanded braces** @@ -687,7 +871,7 @@ Braces are expanded when `` By default, brace patterns work the same way regex logical `OR` operators. For example, `(a|b)` will achieve the same result as `{a,b}`. -Visit [braces](https://github.com/jonschlinkert/braces) to ask questions and create an issue related to brace-expansion, or to see the full range of features and options related to brace expansion. +Visit [braces](https://github.com/jonschlinkert/braces) to see the full range of features and options related to brace expansion, or to create brace matching or expansion related issues. ### regex character classes @@ -708,15 +892,20 @@ Given `['a.js', 'b.js', 'c.js', 'd.js', 'E.js']`: * `(b|d).js`: would match either `b` or `d`, returning `['b.js', 'd.js']` * `(b|[A-Z]).js`: would match either `b` or an uppercase letter, returning `['b.js', 'E.js']` -As with regex, parenthese can be nested, so patterns like `((a|b)|c)/b` will work. But it might be easier to achieve your goal using brace expansion. +As with regex, parens can be nested, so patterns like `((a|b)|c)/b` will work. Although brace expansion might be friendlier to use, depending on preference. ### POSIX bracket expressions +POSIX brackets are intended to be more user-friendly than regex character classes. This of course is in the eye of the beholder. + **Example** ```js mm.isMatch('a1', '[[:alpha:][:digit:]]'); //=> true + +mm.isMatch('a1', '[[:alpha:][:alpha:]]'); +//=> false ``` See [expand-brackets](https://github.com/jonschlinkert/expand-brackets) for more information about bracket expressions. @@ -725,17 +914,41 @@ See [expand-brackets](https://github.com/jonschlinkert/expand-brackets) for more ## Notes -**Bash 4.3 parity** +### Bash 4.3 parity + +Whenever possible matching behavior is based on behavior Bash 4.3, which is mostly consistent with minimatch. + +However, it's suprising how many edge cases and rabbit holes there are with glob matching, and since there is no real glob specification, and micromatch is more accurate than both Bash and minimatch, there are cases where best-guesses were made for behavior. In a few cases where Bash had no answers, we used wildmatch (used by git) as a fallback. + +### Backslashes + +There is an important, notable difference between minimatch and micromatch _in regards to how backslashes are handled_ in glob patterns. + +* Micromatch exclusively and explicitly reserves backslashes for escaping characters in a glob pattern, even on windows. This is consistent with bash behavior. +* Minimatch converts all backslashes to forward slashes, which means you can't use backslashes to escape any characters in your glob patterns. + +We made this decision for micromatch for a couple of reasons: -Whenever possible parsing behavior for patterns is based on globbing specifications in Bash 4.3, which is mostly also constistent with minimatch. Patterns that aren't described in enough detail by the Bash spec follow wildmatch spec (used by git). +* consistency with bash conventions. +* glob patterns are not filepaths. They are a type of [regular language](https://en.wikipedia.org/wiki/Regular_language) that is converted to a JavaScript regular expression. Thus, when forward slashes are defined in a glob pattern, the resulting regular expression will match windows or POSIX path separators just fine. -**Escaping** +**A note about joining paths to globs** -Backslashes are exclusively and explicitly reserved for escaping characters in a glob pattern, even on windows. This is the convention in all globbing libs, including minimatch and node-glob, although some users are [confused about how this works](https://github.com/isaacs/node-glob/issues/212). +Note that when you pass something like `path.join('foo', '*')` to micromatch, you are creating a filepath and expecting it to still work as a glob pattern. This causes problems on windows, since the `path.sep` is `\\`. -To be clear, _a glob pattern is not a filepath_, it's a [regular language](https://en.wikipedia.org/wiki/Regular_language) that is converted to a JavaScript regular expression. When you pass something like `path.join('foo', '*')` to micromatch, you are creating a filepath and expecting it to still work as a glob pattern. This causes problems on windows, since the node.js `path` module converts `/` to `\\` and/or uses `\\` as the path separator when joining paths. Since `\\` is an escape character in globs, on windows `path.join('foo', '*')` would result in `foo\\*`, which tells micromatch to match `*` as a literal character. +In other words, since `\\` is reserved as an escape character in globs, on windows `path.join('foo', '*')` would result in `foo\\*`, which tells micromatch to match `*` as a literal character. This is the same behavior as bash. -To get around this, you can either do the joining manually or find a lib on npm that does this. +## Contributing + +All contributions are welcome! Please read [the contributing guide](.github/contributing.md) to get started. + +**A special note about bug reports** + +Please feel free to create an issue if you find something that you think isn't right. However, especially (but not exclusively) if you find a matching-related issue, please please try do the following first: + +* research existing issues first +* visit the [GNU Bash documentation](https://www.gnu.org/software/bash/manual/) to see how Bash deals with the pattern +* visit the [minimatch](https://github.com/isaacs/minimatch) documentation to cross-check expected behavior ## Benchmarks @@ -749,7 +962,7 @@ npm i -d && npm benchmark ### Latest results -As of December 13, 2016 (longer bars are better): +As of May 28, 2017 (longer bars are better): ```sh # braces-globstar-large-list @@ -801,13 +1014,14 @@ multimatch █████████████████████ (3,39 micromatch ██████████████████████████████████████████████████████████████████████ (9,578 ops/sec) minimatch ████████████████████ (2,865 ops/sec) multimatch ████████████████████ (2,873 ops/sec) + ``` ## About ### Related projects -* [braces](https://www.npmjs.com/package/braces): Fast, comprehensive, bash-like brace expansion implemented in JavaScript. Complete support for the Bash 4.3 braces… [more](https://github.com/jonschlinkert/braces) | [homepage](https://github.com/jonschlinkert/braces "Fast, comprehensive, bash-like brace expansion implemented in JavaScript. Complete support for the Bash 4.3 braces specification, without sacrificing speed.") +* [braces](https://www.npmjs.com/package/braces): Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support… [more](https://github.com/micromatch/braces) | [homepage](https://github.com/micromatch/braces "Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support for the Bash 4.3 braces specification, without sacrificing speed.") * [expand-brackets](https://www.npmjs.com/package/expand-brackets): Expand POSIX bracket expressions (character classes) in glob patterns. | [homepage](https://github.com/jonschlinkert/expand-brackets "Expand POSIX bracket expressions (character classes) in glob patterns.") * [extglob](https://www.npmjs.com/package/extglob): Extended glob support for JavaScript. Adds (almost) the expressive power of regular expressions to glob… [more](https://github.com/jonschlinkert/extglob) | [homepage](https://github.com/jonschlinkert/extglob "Extended glob support for JavaScript. Adds (almost) the expressive power of regular expressions to glob patterns.") * [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`") @@ -817,13 +1031,13 @@ multimatch ████████████████████ (2,873 o Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). -Please read the [contributing guide](.github/contributing.md) for avice on opening issues, pull requests, and coding standards. +Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards. ### Contributors -| **Commits** | **Contributor**
| -| --- | --- | --- | --- | --- | -| 345 | [jonschlinkert](https://github.com/jonschlinkert) | +| **Commits** | **Contributor** | +| --- | --- | +| 346 | [jonschlinkert](https://github.com/jonschlinkert) | | 12 | [es128](https://github.com/es128) | | 3 | [paulmillr](https://github.com/paulmillr) | | 2 | [TrySound](https://github.com/TrySound) | @@ -831,25 +1045,26 @@ Please read the [contributing guide](.github/contributing.md) for avice on openi | 2 | [MartinKolarik](https://github.com/MartinKolarik) | | 2 | [tunnckoCore](https://github.com/tunnckoCore) | | 1 | [amilajack](https://github.com/amilajack) | +| 1 | [DianeLooney](https://github.com/DianeLooney) | | 1 | [UltCombo](https://github.com/UltCombo) | | 1 | [tomByrer](https://github.com/tomByrer) | ### Building docs -_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ -To generate the readme and API documentation with [verb](https://github.com/verbose/verb): +To generate the readme, run the following command: ```sh -$ npm install -g verb verb-generate-readme && verb +$ npm install -g verbose/verb#dev verb-generate-readme && verb ``` ### Running tests -Install dev dependencies: +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: ```sh -$ npm install -d && npm test +$ npm install && npm test ``` ### Author @@ -857,13 +1072,13 @@ $ npm install -d && npm test **Jon Schlinkert** * [github/jonschlinkert](https://github.com/jonschlinkert) -* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) ### License -Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). -Released under the [MIT license](https://github.com/jonschlinkert/micromatch/blob/master/LICENSE). +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). *** -_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.2.0, on December 13, 2016._ \ No newline at end of file +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 28, 2017._ \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 3b8ac52c..ad16679b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,8 +4,8 @@ environment: # node.js - nodejs_version: "7.0" - nodejs_version: "6.0" - - nodejs_version: "4.0" - nodejs_version: "5.0" + - nodejs_version: "4.0" - nodejs_version: "0.12" - nodejs_version: "0.10" diff --git a/docs/minimatch.md b/docs/minimatch.md deleted file mode 100644 index d568279c..00000000 --- a/docs/minimatch.md +++ /dev/null @@ -1,214 +0,0 @@ -# Comparison: micromatch vs. minimatch - -> This document is based on the readme from [minimatch], with additions to show how the two libraries, minimatch and micromatch, compare to one another. - -**Matching with RegExp** - -Both libraries work by converting glob expressions into JavaScript `RegExp` objects. However, there are key differences in approach. - -**Parse > Tokenize > Convert to regex** - -For the most part, both libraries follow this formula. - -- glob pattern is parsed into tokens -- if applicable, pattern is expanded to multiple patterns, as with brace patterns (`/{a,b}/*.js`) - - -**Major implementation differences** - -Micromatch's huge speed advantage comes from a few different areas: - -- basic caching -- tokenization strategy -- regex optimizations -- single responsibility functions - - -**Example compiled regex** - -```js -micro.makeRe('*.{yml,json}'); -//=> /^(?:(?!\.)(?=.)[^/]*?\.(yml|json))$/ - -mini.makeRe('*.{yml,json}'); -//=> /^(?:(?!\.)(?=.)[^/]*?\.yml|(?!\.)(?=.)[^/]*?\.json)$/ -``` - - -## Usage - -```js -var minimatch = require("minimatch"); -var micromatch = require('micromatch'); -``` - -**Minimatch** - -Match the path on the left against the pattern on the right: - -```js -minimatch("foo.js", "*.js"); // true! -``` - -**Micromatch** - -The micromatch equivalent is `micromatch.isMatch()` - - -```js -minimatch.isMatch('foo.js', '*.js'); // true! -``` - - -## Features - -Both libraries support these glob features: - -* Brace Expansion -* Extended glob matching -* "Globstar" `**` matching - - -## Constructor - -**Minimatch Class** - -Create a minimatch object by instanting the `minimatch.Minimatch` class. - -```js -var Minimatch = require("minimatch").Minimatch; -var mm = new Minimatch(pattern, options); -``` - -**Micromatch** - -No support. If you need access to tokens as they are generated (to avoid parsing the glob more than once), you can use `micromatch.expand()`. - - -## Functions - -### minimatch(path, pattern, options) - -Main export. Tests a path against the pattern using the options. - -```js -var isJS = minimatch(file, "*.js", { matchBase: true }) -``` - -### minimatch.filter(pattern, options) - -Returns a function that tests its -supplied argument, suitable for use with `Array.filter`. Example: - -```js -var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true})) -``` - -### minimatch.match(list, pattern, options) - -Match against the list of -files, in the style of fnmatch or glob. If nothing is matched, and -options.nonull is set, then return a list containing the pattern itself. - -```js -var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})) -``` - -### minimatch.makeRe(pattern, options) - -Make a regular expression object from the pattern. - -## Options - -All options are `false` by default. - -### debug - -Dump a ton of stuff to stderr. - -### nobrace - -Do not expand `{a,b}` and `{1..3}` brace sets. - -### noglobstar - -Disable `**` matching against multiple folder names. - -### dot - -Allow patterns to match filenames starting with a period, even if -the pattern does not explicitly have a period in that spot. - -Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot` -is set. - -### noext - -Disable "extglob" style patterns like `+(a|b)`. - -### nocase - -Perform a case-insensitive match. - -### nonull - -When a match is not found by `minimatch.match`, return a list containing -the pattern itself if this option is set. When not set, an empty list -is returned if there are no matches. - -### matchBase - -If set, then patterns without slashes will be matched -against the basename of the path if it contains slashes. For example, -`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. - -### nocomment - -Suppress the behavior of treating `#` at the start of a pattern as a -comment. - -### nonegate - -Suppress the behavior of treating a leading `!` character as negation. - -### flipNegate - -Returns from negate expressions the same as if they were not negated. -(Ie, true on a hit, false on a miss.) - - -## Comparisons to other fnmatch/glob implementations - -While strict compliance with the existing standards is a worthwhile -goal, some discrepancies exist between minimatch and other -implementations, and are intentional. - -If the pattern starts with a `!` character, then it is negated. Set the -`nonegate` flag to suppress this behavior, and treat leading `!` -characters normally. This is perhaps relevant if you wish to start the -pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` -characters at the start of a pattern will negate the pattern multiple -times. - -If a pattern starts with `#`, then it is treated as a comment, and -will not match anything. Use `\#` to match a literal `#` at the -start of a line, or set the `nocomment` flag to suppress this behavior. - -The double-star character `**` is supported by default, unless the -`noglobstar` flag is set. This is supported in the manner of bsdglob -and bash 4.1, where `**` only has special significance if it is the only -thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but -`a/**b` will not. - -If an escaped pattern has no matches, and the `nonull` flag is set, -then minimatch.match returns the pattern as-provided, rather than -interpreting the character escapes. For example, -`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than -`"*a?"`. This is akin to setting the `nullglob` option in bash, except -that it does not resolve escaped pattern characters. - -If brace expansion is not disabled, then it is performed before any -other interpretation of the glob pattern. Thus, a pattern like -`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded -**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are -checked for validity. Since those two are valid, matching proceeds. diff --git a/docs/switching-from-minimatch.md b/docs/switching-from-minimatch.md deleted file mode 100644 index bd7cec44..00000000 --- a/docs/switching-from-minimatch.md +++ /dev/null @@ -1,28 +0,0 @@ -# Switching from minimatch - -> Use `mm.isMatch()` instead of `minimatch()` - -**Minimatch** - -The main `minimatch()` function returns true/false for a single file path and pattern: - -```js -var minimatch = require('minimatch'); -minimatch('foo.js', '*.js'); -//=> 'true' -``` - -**Micromatch** - -With micromatch, `.isMatch()` to get the same result: - -```js -var mm = require('micromatch'); -mm.isMatch('foo.js', '*.js'); -//=> 'true' -``` - -This implementation difference is necessary since the main `micromatch()` method supports matching on multiple globs, with behavior similar to [multimatch][]. - -[multimatch]: https://github.com/sindresorhus/multimatch -[minimatch]: https://github.com/isaacs/minimatch