{"_id":"@isaacs/nonrecursive-glob-match","_rev":"5-7af52498f627095ac44ee06aa4307948","name":"@isaacs/nonrecursive-glob-match","dist-tags":{"latest":"1.0.3"},"versions":{"0.0.0-stage":{"name":"@isaacs/nonrecursive-glob-match","version":"0.0.0-stage","_id":"@isaacs/nonrecursive-glob-match@0.0.0-stage","stub":true,"maintainers":[{"name":"isaacs","email":"i@izs.me"}],"dist":{"shasum":"e4ca5165737f3f8292eba7b466d2aa8892cf475c","tarball":"https://registry.npmjs.org/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-HabTLGP2f3bm+9yN/4uDT2IcQoQnul9m7vbwKaEEDN3O/QRx5Ob5FfS9MaF7F5WOD+GxDd43zMNKlyr8E0vl1w==","signatures":[{"sig":"MEUCIAa3e5Nv0Fm8cL8x/DTwnbfsQK3a9SrwupB2JPEDh5uxAiEA76BXby89hwchLeBJxGyWyIxxHHhe6Z12ixOIurORrpc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":353},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"description":"Temporary package placeholder for staged publishing","directories":{}},"1.0.0":{"name":"@isaacs/nonrecursive-glob-match","version":"1.0.0","license":"BlueOak-1.0.0","_id":"@isaacs/nonrecursive-glob-match@1.0.0","maintainers":[{"name":"isaacs","email":"i@izs.me"}],"dist":{"shasum":"4aa3895795d262a94fffcd166a3444455091f4ce","tarball":"https://registry.npmjs.org/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-1.0.0.tgz","fileCount":27,"integrity":"sha512-01oEw4Z54J3lAhxw6IblmuVO6vzcu+2bkb0XuUi3z/fQsdn4+Y7ioRUoS8TuIGQ2naBSxQ+WCd4/O75UDcjANA==","signatures":[{"sig":"MEQCIHjHY+Sb6svbO4sX5jeQsXQ8ddId465rolZ3oQ8XIrWEAiBa1eVapm28CW4vDASFfPCH7seB1qHRh9amL7tQOKhu0g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDGIl00mH+zhe4Sokha7EFmm5GMZ7Jklw0xvPof6356qAIhAPPI2+aIz3iFoDyBr4u+JDV3ChBgBLuraAowVZzta7II","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":214731},"main":"./dist/commonjs/index.js","tshy":{"exports":{".":"./src/index.ts","./package.json":"./package.json"},"selfLink":false},"type":"module","types":"./dist/commonjs/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"647c6487a7d13a94efaa71e43d3df47c0bc59ed1","scripts":{"snap":"tap","test":"tap","format":"prettier --write .","prepare":"tshy && bash scripts/build.sh","presnap":"npm run prepare","pretest":"npm run prepare","typedoc":"typedoc","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"_npmVersion":"12.2.0","description":"a single-path-portion glob matcher not subject to recursive backtracking ReDoS","directories":{},"_nodeVersion":"26.5.0","allowScripts":{"esbuild@0.28.2":true},"_hasShrinkwrap":false,"devDependencies":{"tap":"^21.8.0","tshy":"^4.1.3","esbuild":"^0.28.2","typedoc":"^0.28.20","prettier":"^3.9.10"},"_npmOperationalInternal":{"tmp":"tmp/nonrecursive-glob-match_1.0.0_1793058958885_0.09966716271091358","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@isaacs/nonrecursive-glob-match","version":"1.0.1","license":"BlueOak-1.0.0","_id":"@isaacs/nonrecursive-glob-match@1.0.1","maintainers":[{"name":"isaacs","email":"i@izs.me"}],"dist":{"shasum":"1a652412dcfe533c0ec57097e5bbaef00ba1b6ff","tarball":"https://registry.npmjs.org/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-1.0.1.tgz","fileCount":27,"integrity":"sha512-rNKPuTXBacPpn5+CP+S3/UI6uq/0jHZjPpaBLaRE3blpgX+E+ZUIrGfViPvUjUnQG6W1+3OTFUiVRCjTffs2+Q==","signatures":[{"sig":"MEYCIQCWAFliLvgofzDnEWY3rrDN81he2s6UpqUQzKI85tHJ9AIhANdjU3pQ6ChtfgFCsM0gaDuMM/nqN5bBKq9J/26rl8R8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDtej3jdcCTtM/DkfsyOH5NAb6bpd19Mn2ZmMr446MS5QIgPPYV98HV5f1ZdUCj8legDPvXFROA71HFqIsj9aXVhWY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":375098},"main":"./dist/commonjs/index.js","tshy":{"exports":{".":"./src/index.ts","./package.json":"./package.json"},"selfLink":false},"type":"module","types":"./dist/commonjs/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"f4a6260f1589562a67dd990b8059469f87d75658","scripts":{"snap":"tap","test":"tap","format":"prettier --write .","prepare":"tshy && bash scripts/build.sh","presnap":"npm run prepare","pretest":"npm run prepare","typedoc":"typedoc","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"_npmVersion":"12.2.0","description":"a single-path-portion glob matcher not subject to recursive backtracking ReDoS","directories":{},"_nodeVersion":"26.5.0","allowScripts":{"esbuild@0.28.2":true},"_hasShrinkwrap":false,"devDependencies":{"tap":"^21.8.0","tshy":"^4.1.3","esbuild":"^0.28.2","typedoc":"^0.28.20","prettier":"^3.9.10"},"_npmOperationalInternal":{"tmp":"tmp/nonrecursive-glob-match_1.0.1_1793075092434_0.4287135020905376","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@isaacs/nonrecursive-glob-match","version":"1.0.2","license":"BlueOak-1.0.0","_id":"@isaacs/nonrecursive-glob-match@1.0.2","maintainers":[{"name":"isaacs","email":"i@izs.me"}],"dist":{"shasum":"aeaab8a9a4bbc3c406f8c12ff674227ea78a6028","tarball":"https://registry.npmjs.org/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-1.0.2.tgz","fileCount":27,"integrity":"sha512-GJPHIgPPtFl+nLhFHyF0zZoFcOFLsZWbHFFzo+Zr+PWDXJbl9hHxb2w+9SiF2fHmLgKaXIpUzQo3SbBBZ9WObw==","signatures":[{"sig":"MEUCIQDNLx1nWbvNgEM3SuPO1iUv6/zagdY57FwutkEPobgPKQIgHRVpvqwSRP4wtWuXzDVta2m7OHyuw1oBhPiR8fyYFOE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDsFM/35UjbqiNnwnzGEDDILP2IvsUvzZO1/8jHNY0cIAiBXWJE3ZgJesQLhABgguRxNnV/x23FxDOwE/6tahj+kBw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":375238},"main":"./dist/commonjs/index.js","tshy":{"exports":{".":"./src/index.ts","./package.json":"./package.json"},"selfLink":false},"type":"module","types":"./dist/commonjs/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"974ce46223ca23c9c0c6606b46990379bf5adead","scripts":{"snap":"tap","test":"tap","format":"prettier --write .","prepare":"tshy && bash scripts/build.sh","presnap":"npm run prepare","pretest":"npm run prepare","typedoc":"typedoc","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"_npmUser":{"name":"isaacs","email":"i@izs.me"},"_npmVersion":"12.2.0","description":"a single-path-portion glob matcher not subject to recursive backtracking ReDoS","directories":{},"_nodeVersion":"26.5.0","allowScripts":{"esbuild@0.28.2":true},"_hasShrinkwrap":false,"devDependencies":{"tap":"^21.8.0","tshy":"^4.1.3","esbuild":"^0.28.2","typedoc":"^0.28.20","prettier":"^3.9.10"},"_npmOperationalInternal":{"tmp":"tmp/nonrecursive-glob-match_1.0.2_1793149303473_0.14217330361023095","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"_id":"@isaacs/nonrecursive-glob-match@1.0.3","dist":{"shasum":"7f6724fd8a6ca315d6bb7f63f0e4d079060da246","tarball":"https://registry.npmjs.org/@isaacs/nonrecursive-glob-match/-/nonrecursive-glob-match-1.0.3.tgz","fileCount":27,"integrity":"sha512-SI7kyKHq4XXDRozw+r9GlRZkia1ZkFrpLW98r2IC2Bpr8YkFGE3fvjzmxCG0x78A++69HmDNrDvSMYBZmHGpKA==","signatures":[{"sig":"MEUCIA4GJUf23A129PUQ73yCYoNaqEPQ7PyPM5YC0LTtWSLfAiEA9Z+5rN1SrdknDvojjmrj4AZUL9sEdRhwQWPKhgLYe/I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDIbzXJ8t8drJFYHulUB6/wOn6mmUBdiWZjGNEX9Dv8iwIhALNsTZvNisHuduHE4MSsbkx6gn5/6RmdZwGGIaq8ONul"}],"unpackedSize":380111},"main":"./dist/commonjs/index.js","name":"@isaacs/nonrecursive-glob-match","tshy":{"exports":{".":"./src/index.ts","./package.json":"./package.json"},"selfLink":false},"type":"module","types":"./dist/commonjs/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.js"}},"./package.json":"./package.json"},"gitHead":"ad4131ad08b78e80215add95cfd2afcc90518187","license":"BlueOak-1.0.0","scripts":{"snap":"tap","test":"tap","format":"prettier --write .","prepare":"tshy && bash scripts/build.sh","presnap":"npm run prepare","pretest":"npm run prepare","typedoc":"typedoc","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags"},"version":"1.0.3","_npmUser":{"name":"isaacs","email":"i@izs.me"},"_npmVersion":"12.2.0","description":"a single-path-portion glob matcher not subject to recursive backtracking ReDoS","directories":{},"maintainers":[{"name":"isaacs","email":"i@izs.me"}],"_nodeVersion":"26.5.0","allowScripts":{"esbuild@0.28.2":true},"_hasShrinkwrap":false,"devDependencies":{"tap":"^21.8.0","tshy":"^4.1.3","esbuild":"^0.28.2","typedoc":"^0.28.20","prettier":"^3.9.10"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nonrecursive-glob-match_1.0.3_1793217048203_0.004277296658946161"}}},"time":{"created":"2026-10-26T23:53:21.802Z","modified":"2026-10-28T19:50:48.589Z","0.0.0-stage":"2026-10-26T23:53:21.802Z","1.0.0":"2026-10-26T23:55:58.986Z","1.0.1":"2026-10-27T04:24:52.559Z","1.0.2":"2026-10-28T01:01:43.656Z","1.0.3":"2026-10-28T19:50:48.349Z"},"license":"BlueOak-1.0.0","description":"a single-path-portion glob matcher not subject to recursive backtracking ReDoS","maintainers":[{"name":"isaacs","email":"i@izs.me"}],"readme":"# @isaacs/nonrecursive-glob-match\n\nThis is a glob matcher that can be applied to a single path\nportion (ie, not `/`), which completes in polynomial time because\nit doesn't compile to Regular Expressions or any other\nbacktrack-dependent algorithm.\n\n## USAGE\n\n```ts\nimport { Matcher } from '@isaacs/nonrecursive-glob-match'\n\nconst m = new Matcher('a*a!(y|z)')\n\nconsole.log(m.test('abcay')) // false\nconsole.log(m.test('abcax')) // true\nconsole.log(m.test('aa')) // true\n```\n\nThe pattern and the tested string must be a single path portion.\nIf either one contains a `/` character, the matcher throws an\nerror.\n\nIf you already split a path on `/`, use `m.testUnchecked(s)`. It\ngives the same result as `m.test(s)`, but it does not check `s`\nfor a `/` character. This can make it faster, because some\npatterns, such as `*.js`, then do not need to look at each\ncharacter. If `s` has a `/`, the result is not defined.\n\n## Why\n\nPatterns like this frustrate most glob matchers: `a*a*a*a*a*a*a`.\nThey can be used to take down servers if applied to untrusted\ninput. Fixing these vulns is like playing whack-a-mole with the\nwhole internet.\n\nIf compiled to a regular expression like\n`/^a[^/]*a[^/]*a[^/]*a[^/]*a[^/]*a[^/]*a$/`, and then applied to\na path portion like `aaaaaaaaaaaaaaaaaaab`, the engine must check\nevery possible path through the pattern, constantly rewinding\nback to the first character each time and trying a different\nnumber of `a` characters matched against the `[^/]*` to see if it\nmatches. Because nothing matches, it must test every possible\npath before ultimately giving up.\n\nIn contrast, the algorithm presented here is based on the\nThompson NFA paper from 1968, which tests every possible path\nthrough the string at the same time, so that it only has to walk\nthe string one time. This algorithm is also implemented in the\nRegExp engines used by `egrep` and `awk`, which is why those\ntools are so fast, even when matching complicated RegExps against\nextremely large strings.\n\nThe `Matcher` objects have a `test` method which takes a string,\njust like a `RegExp` object, and can be a drop-in replacement for\nthe regular expressions used in minimatch and other matchers.\nHowever, they are _not_ a complete drop-in replacement for a\nRegExp, so be careful when replacing one with the other. (For\nexample, they do not capture, do not track match indexes, no\nfancy RegExp features, etc.)\n\n## Patterns Supported\n\nHere are the patterns supported, and their effective state\nmachines drawn in lovely ASCII diagrams.\n\n### `*` 0 or more of any character, not starting with `.`\n\n```\n--+-------------------+->\n  v                   ^\n  +<------------------+\n  v                   ^\n  +-->any character-->+\n```\n\n### `?`\n\n```\n-->any character-->\n```\n\n### `[<set>]`\n\n```\n-->character in set-->\n```\n\nThis covers named posix sets like `[[:alpha:]]` as well as\ncharacter classes like `[a-b]`. (In this case, a regular\nexpression actually is compiled, but it's not subject to ReDoS,\nbecuase it's just a `/[a-z]/` style pattern tested against one\ncharacter at a time.)\n\n### `@(e1|e2|...)`\n\n\"One\" extglob.\n\n```\n--+--> e1 -->+-->\n  v          ^\n  +--> e2 -->+\n  v          ^\n  +--> e3 -->+\n  v   ...    ^\n```\n\n### `?(e1|e2|...)`\n\n\"Zero or one\" extglob.\n\n```\n--+--------->+-->\n  v          ^\n  +--> e1 -->+\n  v          ^\n  +--> e2 -->+\n  v          ^\n  +--> e3 -->+\n  v   ...    ^\n```\n\n### `*(e1|e2|...)`\n\n\"Zero or more\" extglob.\n\n```\n--+--------->+-->\n  v          ^\n  +<---------+\n  v          ^\n  +--> e1 -->+\n  v          ^\n  +--> e2 -->+\n  v          ^\n  +--> e3 -->+\n  v   ...    ^\n```\n\n### `+(e1|e2|...)`\n\n\"One or more\" extglob.\n\n```\n  +<---------+\n  v          ^\n--+--> e1 -->+-->\n  v          ^\n  +--> e2 -->+\n  v          ^\n  +--> e3 -->+\n  v   ...    ^\n```\n\n### `!(e1|e2|...)`\n\n\"Negative\" extglob.\n\nThe challenge with negation is that it opens the door to a whole\nheap of edge cases. Especially, _any_ expression can be nested\ninside the negation, and it needs to match anything at all, as\nlong as it _doesn't_ match one of the supplied patterns. This is\nwhere it gets complicated, and past attempts have run into\nproblems.\n\nWe handle this by starting a \"Run\" that technically does recurse,\nand thus can push the performance out from `O(n * m)` to\n`O(n * m * r)` where `n` is the string length, `m` is the pattern\nlength, and `r` is the number of negative extglob portions it\ncontains. In practice, this is limited by the pattern length, and\nstill doesn't allow ReDOS-style explosive recursive backtracking,\nso this is fine.\n\n## Unicode Normalization\n\nA char such as `é` can be one code point (U+00E9), or `e`\nfollowed by a combining accent (U+0301). Some file systems, such\nas on macOS, can give file names in the second form. These two\nforms do not match by default.\n\nSet the `normalize` option to normalize the pattern and each\ntested string to the same form. Use `'NFC'`, `'NFD'`, `'NFKC'`,\nor `'NFKD'`. `true` means `'NFC'`.\n\n```ts\nconst m = new Matcher('café', { normalize: true })\nm.test('café') // true\n```\n\n- Use NFC if you are not sure. With NFD and NFKD, `é` is two\n  code points. Then `?` does not match `é`, and `[é]` can not\n  match it.\n- NFKC and NFKD also fold compatibility chars. For example, `ﬁ`\n  matches `fi`, and full-width `Ａ` matches `A`.\n- Syntax is parsed before normalization. So, a char that\n  normalizes to a syntax char stays a literal. For example, with\n  NFKC, full-width `＊` matches only `*` or `＊`, and it is not a\n  wildcard.\n- Each run of literal chars normalizes as one string. Each member\n  of a `[...]` class normalizes on its own, and stays as it is if\n  its normal form is more than one code point.\n- A combining mark after a wildcard is its own literal, and does\n  not compose with the char that the wildcard matches. So, with\n  NFC, `?́` does not match `é`. With NFD, it does match,\n  because `é` is also two code points in the string. Patterns\n  match code points, not grapheme clusters.\n- With `nocase`, normalization comes first, then case folding.\n- The `/` check uses the strings as given. So, full-width `／`\n  does not cause an error.\n\n## Differences from Bash\n\nBash 5 is the reference for this module, with two known\ndeviations.\n\n### Dotfiles\n\nIf `dot` is not set, a string that starts with `.` only matches\nif a literal `.` in the pattern matches that first character.\nExtglobs before that `.` can match the empty string, and the\npattern can still match. For example, `!(.a|js)@(.*)` matches\n`.a`, `.a.js`, and `.js`, because `!(.a|js)` matches the empty\nstring, and `@(.*)` matches the rest. Bash does not match these\ndotfiles. See [this bug\nreport](https://lists.gnu.org/archive/html/bug-bash/2026-03/msg00034.html).\n\nA `*` can never match at the start of a dotfile, even if it\nmatches the empty string. So, `*.js` does not match `.js`, as in\nBash.\n\n### Case-insensitive matching\n\nBash compares chars with the case functions of the C library for\nthe current locale. So, the results can change with the locale\nand the platform.\n\nWith `nocase`, this module uses Unicode simple case folding, one\ncode point at a time. This is the same folding that a JavaScript\nRegExp uses with the `iu` flags. It does not change with the\nlocale, and literals, `[...]` classes, and ranges all use it.\n\n- `Σ`, `σ`, and final sigma `ς` all match each other.\n- The micro sign `µ` matches `μ` and `Μ`. The Kelvin sign `K`\n  matches `k`. The Angstrom sign `Å` matches `å`.\n- `ẞ` matches `ß`, but `ß` does not match `ss`. A fold never\n  changes the number of chars, so ligatures such as `ﬁ` do not\n  match `fi`.\n- There are no Turkish rules. `I` matches `i`, but dotted `İ`\n  and dotless `ı` only match themselves.\n\n## Algorithm\n\nA glob pattern is parsed and compiled into a series of attached\nstate machines.\n\nFor example, the glob patttern `*(a|[c-d]|+(x|y|z))z` would\ncompile to a state machine something like the following flow\ndiagram:\n\n```\n-->+----------------------->+-->8 LITERAL(z)-->9 end\n   v                        ^\n   +<-----------------------6\n   v                        ^\n   0-->LITERAL(a)---------->|\n   v                        |\n   1-->CLASS(c-d)---------->|\n   v                        |\n   2-->+<---------------+-->+\n       v                ^\n       3-->LITERAL(x)-->7\n       v                |\n       4-->LITERAL(y)-->|\n       v                |\n       5-->LITERAL(z)-->+\n```\n\nThen, for each character in the string, we walk through the\nresulting graph until we find a test node.\n\nThese test nodes are all executed on the current character, and\nfor any tests pass, their output nodes are added to the walk, and\nwe proceed to walk until hitting a test node again.\n\nBecause all routes eventually get to the exit, which only passes\nwhen the string is at its last character, we are guaranteed to\neventually either fail (and have no more states to process), or\nexit with a match.\n\nAt each branching point, effectively we increase the memory usage\nby a tiny bit to track which nodes are being processed, but\nimportantly, we _don't_ have to try all the way to the exit and\nthen backtrack recursively, storing multiple states of the string\nin an exponential explosion.\n\nA pattern like `a*a*a*a*a*a*a*a*a*a*a`, which could be naively\nconverted into a Regular Expression\n`^a.*a.*a.*a.*a.*a.*a.*a.*a.*a.*a$`, would take over 33 seconds\nto match the string `'a'.repeat(50) + 'b'` using standard\nJavaScript regular expressions, because it must attempt every\npossible grouping of characters, backtracking after each failure.\n\nBy contrast, this implementation can solve this match for either\na pass or failure in roughly the same amount of time, which\nis bound by `C * N`, where `C` is the number of states in the\nmachine, and `N` is the length of the string, finishing both\nfailure and success cases in polynomial time.\n\nEven on the first rather naive implementation in JavaScript, with\nno optimizations for repeated `*` or other common tweaks, this\nfinishes in 300-400 µs for the pathological case described, and\nas the numbers increase, this time rises roughly linearly.\n\nThat's somewhat worse than RegExp's performance in the _success_\ncase, which is around 40µs, but as it's around 100,000x faster in\nthe failure case, this is already quite promising. And, future\niterations of this can likely bring that performance closer to\nthe native RegExp implementation.\n\n## Acknowledgement\n\nThe algorithm and ideas in this implementation are inspired,\nborrowed, and at times outright stolen from [Russ\nCox](https://research.swtch.com)'s explanation of Ken Thompson's\nwork in [Regular Expression Matching Can Be Simple And\nFast](https://swtch.com/~rsc/regexp/regexp1.html). I am both\nimpressed by and grateful for their work.\n\nThe code here in this library was written entirely by me, [Isaac\nZ. Schlueter](https://izs.me), and so you should not blame either\nof them (or anyone else) for any problems it might have. You\nshould also not blame me. It's open source, after all, no\nwarrantees express or implied, etc.\n","readmeFilename":"README.md"}