A regular expression to check URL structure for jsfiddle links

How can I check if a given string is a valid URL address in the following format:

jsfiddle.net/test/wLrk94mp

  • If a user prefixes the URL with https:// or http:// or http://www I’d like to remove it
  • If a user adds a trailing slash to the end of the URL i.e. jsfiddle.net/test/wLrk94mp/, I’d like to remove it.

Here’s my line of thinking so far (pseudocode):

  1. Check if jsfiddle.net exists in the string with indexOf('jsfiddle.net')
  2. Remove any URL prefixes
  3. Remove any trailing slashes
  4. Check if string can be split into 3 parts (jsfiddle, test, wLrk94mp)
  5. If 1-4 are met then it is a good URL, if not then fail with error

Is there a way of approaching this with regex may as a one-liner, or should I stick with the linear step by step approach as above?

Answer

You could use a super fancy Regex. Note that the look behind feature (?<=) is not supported in all browsers.

const testCases = ['https://jsfiddle.net/test/wLrk94mp/', 'http://www.jsfiddle.net/test/wLrk94mp', '///jsfiddle.net/test/wLrk94mp/', 'www.jsfiddle.net/test/wLrk94mp/', '//www.jsfiddle.net/test/wLrk94mp', 'https://jsfiddle.net/test/wLrk94mp#hi/there', '/jsfiddle.net/test/wLrk94mp?hi=there#foo=bar', 'https://jsfiddle.net/test/wLrk94mp?hi=there'];

testCases.forEach((testCase) => {
  console.log(
    testCase.replace(/((/+|https?://)?(www.)?(?=jsfiddle.net/test/.{8})|(?<=jsfiddle.net/test/.{8})/*([?#].*)?)/gi, '')
  );
});

Let’s go through the Regex

Here it is: /((/+|https?://)?(www.)?(?=jsfiddle.net/test/.{8})|(?<=jsfiddle.net/test/.{8})/*([?#].*)?)/gi

Let’s break it down a bit though.

/ ... /gi

First, we’re going to make a Regex with the flags “g” and “i”. “g” stands for global, which means it will replace all matches, not just the first one. The “i” flag stands for case insensitive, which means we can pass in any kind of capitalisation. This is optional, if you are expecting lowercase text every time.

(/+|https?://)?

This checks for either /, //, ///, http://, or https://. Brackets denotes a capture group, with the question mark indicating that certain characters or groups are optional. This is to replace any of the protocol bits in a URL.

(www.)?

This just replaces any www. in front of a URL with nothing. This too is an optional group.

(?=jsfiddle.net/test/.{8})

This is a positive lookahead – it checks that the string provided does actually contain the pattern “jsfiddle.net/test/8 characters`, without including it in the search result of a Regex.

( ... | ... )

Simple or operator, to match this second group:

(?<=jsfiddle.net/test/.{8})

Same test pattern, but this time a negative lookahead. This allows us to check that the part BEFORE matches the jsfiddle pattern without including it in the search result.

/*

Checks for 0 or more trailing slashes.

([?#].+*)?

Checks if there is a trailing hashtag or slash. If so, also check if there is 0 or more trailing characters after it. This entire group is optional once again.


Usage

Just use str.replace(/((/+|https?://)?(www.)?(?=jsfiddle.net/test/.{8})|(?<=jsfiddle.net/test/.{8})/*([?#].*)?)/gi, ''); where str is any String.


Edit: Testing for a valid JSFiddle URL

The OP replied to another answer asking about validation. This can be done using the following JS:

const testCases = ['https://jsfiddle.net/test/wLrk94mp#hello/there', '//tsfiddle.net/test/wLrk94mp//', 'http://www.jsfiddle.net/test/wLrk94mp//', 'not a link'];

testCases.forEach(testCase => {
  if (testCase.match(/((///?|https?://)?(www.)?jsfiddle.net/test/.{8}?([?#].*)?)/gi))
    return console.log(true, testCase);
  console.log(false, testCase);
});

Leave a Reply

Your email address will not be published. Required fields are marked *