2

I search on SO and on google a good validation regex to detect FULL NPM / other package name (package name(@)version number - all formats).
Now, before you mark this question as duplicate, I must say I searched over here and none of what I found has worked for me:
Regex to parse package name and version number from nuget package filenames
A regex for version number parsing
npm/validate-npm-package-name
Semantic versioning regex
package-name-regex
semver-regex

I also tried a couple of regex myself but none of them do the work for any edge case:

const regex = new RegExp(/(\^|\~?)(\d|x|\*)+\.(\d|x|\*)+\.(\d|x|\*)+/g);
const isScriptVersion = regex.test('imagesloaded@4.1');
if (isScriptVersion) {
}

or

const regex = new RegExp('^(.*?)\.((?:\.?[0-9]+){3,}(?:[-a-z]+)?)');
console.log(regex.test('imagesloaded@4.1'));

Also tried with 3th party NPM packages but not so luck:

const packageNameRegex = require('package-name-regex')
console.log(packageNameRegex.test('font-awesome@5.11.2'))

const semverRegex = require('semver-regex');
console.log(semverRegex().test('font-awesome@5.11.2'));

Here is my test list:

ansi-escapes@^4.3.1
babel-eslint@^10.1.0
chance@^1.1.7
cli-cursor@^3.1.0
eslint@^7.13.0
faker@^5.1.0
forever-monitor@^3.0.1
fs-extra@^9.0.1
lorem-ipsum@^2.0.3
micromatch@^4.0.2
mongoose@^5.10.13
puppeteer@^5.4.1
puppeteer-extra@^3.1.15
puppeteer-extra-plugin-stealth@^2.6.3
random-email@^1.0.3
random-useragent@^0.5.0
random-words@^1.1.1
slice-ansi@^4.0.0
uuid@^8.3.1
validator@13.1.17
wrap-ansi@^7.0.0
font-awesome@5.11.2
react-dom@16.13.1
bootstrap@4.5.2
moment-duration-format@2.3.2

All of the above work with

/(\^|\~?)(\d|x|\*)+\.(\d|x|\*)+\.(\d|x|\*)+/g

However
The following don't work for me:

imagesloaded@4.1
flickity@2.0
lomster@1
example@1.1.1.1.1
example-package@3.12.45.66.34.2
unicorn@1.2.3-alpha.10.beta.0
rainbow@v1.1.1

Many thanks to you all. Cheers.

anubhava
  • 761,203
  • 64
  • 569
  • 643
Or Assayag
  • 5,662
  • 13
  • 57
  • 93
  • 1
    Don't use `new RegExp`, just use a regex literal. Especially your second attempt uses a string literal where the backslashes are not escaped. – Bergi Nov 17 '20 at 18:03
  • 1
    Did you take a look at the source codes of `package-name-regex` and `semver-regex` and try to combine their regular expressions into one? Alternatively you could split on the `@` character (of which there should only be one…) and test for package name and semver string separately. – Bergi Nov 17 '20 at 18:05
  • @Bergi thanks for the comments. anubhava already solved the issue for me. Thanks! – Or Assayag Nov 17 '20 at 18:18

1 Answers1

5

You may try this regex:

/@[~^]?([\dvx*]+(?:[-.](?:[\dx*]+|alpha|beta))*)/g

RegEx Demo

RegEx Details:

  • @: Match a @
  • [~^]?: Match an optional ~ or ^
  • (: Start a capture group #1
    • [\dvx*]+: Match 1+ of digit or v or x or * characters
    • (?: Start a non-capture group
      • [-.]: Match a - or .
      • (?:[\dx*]+|alpha|beta): Match 1+ of digit or v or x or * characters or alpha or beta
    • )*: End non-capture group. * means match 0 or more of this group
  • ): End capture group #1
anubhava
  • 761,203
  • 64
  • 569
  • 643