How to match string with a wildcard in javascript - javascript

I am trying to write a function that checks if a route is included in an array of routes:
const routes = ['/test', '/documentation/*']
function checkRoute(route) {
if (routes.includes(route)) {
console.log('Included!!')
} else {
console.log('Not included!')
}
}
The part I need help with is how to handle the wildcard * - basically, I want any route that has the /docs/ prefix to be included such as:
/documentation/docs.json, /documentation/index.html
Besides doing some very messy string manipulation, I am not sure how to achieve this. Any help would be greatly appreciated!

You can use regex.
const routes = ['\\/test\\/*', '\\/documentation\\/*']
function checkRoute(route) {
let regex = new RegExp(route);
let matchedRoutes = routes.filter(route => regex.test(route))
}

Here is a simple form of wildcard match function. It is not a bad idea to use it and support all types of wildcard comparrsion:
https://stackoverflow.com/a/32402438/635891

Related

Check if two URL strings are equal

I'm building out a function to handle dynamic phone number swapping, identifying the referral url, mapping through a data set, and then outputting the promoUrl's related phone number. The data is formatted like this:
const phoneNumbers = [
{
promoUrl: '/interior-doors/',
promoNumber: '589-918-0710',
},
{
promoUrl: '/promo4/',
promoNumber: '307-789-8615',
},
];
And the function maps through the data and reduces it, allowing me to sort through it like this:
const url = location.pathname.replace(/\/+$/, '');
const promoNumber = phoneNumbers.reduce((promoNumber, results) => {
const hasPromo = results.promoUrl.includes(url);
if (hasPromo) {
return results.promoNumber;
}
return promoNumber;
}, '');
I'm having some issues with hasPromo. The way it's built right now allows for the promoUrl to have some variance and still work, meaning as long as it includes what is returned from url then it works i.e. /interior-doors/, /interior-doors, and interior-doors will all work, which is great, but it also works if url is /interior-do. I need it to not do that. It should work independent of formatting, but only return the promoNumber if the string of letters is exact.
I'm assuming this is a regex thing, but I don't know what I'm doing with regex. Any help would be greatly appreciated.
Use == to do an exact match. And since the promoURL property always has / around it, add those delimiters when you set url
const url = '/' + location.pathname.replace(/\/+$/, '') + '/';
const promoNumber = phoneNumbers.reduce((promoNumber, results) => {
const hasPromo = results.promoUrl == url;
if (hasPromo) {
return results.promoNumber;
}
return promoNumber;
}, '');
reduce also seems like the wrong function for this. You just need to find the matching promoUrl, you don't have to continue reducing, since the reduction function doesn't merge the results in any way.
const promo = phoneNumbers.find(({promoUrl}) => promoUrl == url);
const promoNumber = promo ? promo.promoNumber : '';

Wildcard redirects with javascript?

I'm trying to match URLs at a specific path and redirect them to a subdomain (don't ask why I'm doing this in Javascript).
Basically I can do this for the basics, this is on a page at example.com:
if (window.location.pathname == "/weddings" || window.location.pathname == "/weddings/"){
window.location.replace("https://blog.example.com/weddings/");
}
But now I need to do something similar for wildcards. I need to match /weddings/* and redirect to https://blog.example.com/weddings/*.
How do I do this with Javascript?
UPDATE
This seems to work, but is this the best method?
if (window.location.pathname.startsWith("/weddings/")) {
window.location.replace("https://blog.example.com" + window.location.pathname);
}
You can try this sample code.
const urlRegex = '/weddings/*';
if (window.location.pathname.match(urlRegex) !== null){
window.location.replace("https://blog.example.com/weddings/");
}
You could use String.prototype.match with regex
const regex = /\/weddings\/(.*)/
const pathnames = [
"/wedding",
"/weddings",
"/weddings/",
"/weddings/a",
"/weddings/b",
"/weddings/c/d?e=f",
]
pathnames.forEach((pathname) => {
const match = pathname.match(regex)
if (match) {
console.log(`https://blog.example.com/weddings/${match[1]}`)
}
})
Reference
String.prototype.match()
You can simplify this with URL API
The properties are are the same as window.location so you can check what's in the pathname and change the host accordingly. Then redirect to the resultant
Simplified example looping over a couple of test cases for demo purposes:
For live version just use new URL(location.href)
const samples = [
'http://example.com/food/',
'http://example.com/weddings/',
'http://example.com/weddings/nice-one',
'http://example.com/weddings/foo?param=1'
]
samples.forEach(str => {
const url = new URL(str);
if (url.pathname.startsWith('/weddings')) {
url.host = 'blog.' + url.host;
}
console.log(url.href)
})

Using ES6 Maps for react-router, how can we tweak Map.get?

I have created a map with new Map() to store my RR4 configuration in my app.
I want to access the values of /countries/:id, when I get /countries/1
routesMap.get('/countries/1')
// should return the same as to routesMap.get('/countries/:id')
routesMap.get('/countries/1/comments/20');
// should match routesMap.get('/countries/:countryId/comments/:id')
By creating a class from Map, how can I tweak the get so it become more intelligent to get my react-router-dom path ?
A simple attempt would be something like the following
class RouteMap extends Map {
get(key) {
let match;
// exact match
if (this.has(key)) return super.get(key);
// not exact match, need to apply logic
for (let route of this.keys()) {
const reg = new RegExp(`^${route.replace(/:\w+/g,'\\w+')}$`);
if (!match && reg.test(key)) match = route;
}
return super.get(match);
}
}
const routesMap = new RouteMap();
routesMap.set('/countries/:id', 'just id')
routesMap.set('/countries/:countryId/comments/:id', 'id and country')
console.log(routesMap.get('/countries/:id'));
console.log(routesMap.get('/countries/1'));
console.log(routesMap.get('/countries/:countryId/comments/:id'));
console.log(routesMap.get('/countries/1/comments/20'));
But might need further work to become more flexible, performant and handle edge cases like trailing / etc.

How to Combine Multiple Return Functions (JavaScript)

I am learning JavaScript so that I can implement Google Tag Manager. I have a list of paths that I would like GTM to rewrite to something friendlier like so:
function() {
return document.location.pathname.indexOf('/l/138281/2016-06-07/dy383') > -1 ? 'Test Success' : undefined;
}
function() {
return document.location.pathname.indexOf('/l/138281/2016-04-03/55z63') > -1 ? 'SPP Contact Success' : undefined;
I'm just not sure how to combine these returns into one function (I currently have about 30 URLs to rewrite). I imagine I can use if/else, but advice would be quite lovely.
--edit--
URL Path Rewrite To
/test-638-jsj /test-success
/spp-zxcv-765 /spp-contact-success
/foo-asdf-123 /foo
/foo-bar-987 /foo-bar
The return function mentioned above does this beautifully for an individual link. I just want to be able to rewrite a series of URLs in one function (or however it makes sense to do this most specifically). Hopefully that helps clarify.
Thanks!
It is always a great idea to structure your code: separate abstract functionality from the specific problem.
What you are actually doing is scannins strings for occurences of keywords and returning specific values if such a keyword has been found.
Therefore, you need a function performing the above computation and a JavaScript datastructure holding your keywords and their values (= Object):
// Return patterns[key] if any key is found in string, else return string:
function match(string, patterns) {
for (key of Object.keys(patterns)) {
if (string.indexOf(key) > -1) return patterns[key];
}
return string;
}
var patterns = {
'/l/138281/2016-06-07/dy383': 'Test Success',
'/l/138281/2016-04-03/55z63': 'SPP Contact Success'
}
console.log(match('/l/138281/2016-06-07/dy383', patterns)); // "Test Success"
console.log(match('/doesnotexist', patterns)); // "/doesnotexist"
console.log(match(document.location.pathname, patterns));

Template strings stored as constants

I have a template string:
function getTemplateString () {
let videoId = 'qwerty'
return `https://player.vimeo.com/video/${videoId}?api=1`
}
I want to store this template string in a const instead:
const VIMEO_EMBED_URL = `https://player.vimeo.com/video/${videoId}?api=1`
function getTemplateString () {
let videoId = 'qwerty'
// how can I do this next line?
return VIMEO_EMBED_URL.something({videoId: videoId})
}
Can I do string interpolation on constants?
Template Strings cannot be stored, they return a String when they're defined. So I guess you're looking for a RegExp.
function getTemplateString (url, value) {
return url.replace(/\${video1}/g, value)
}
Other option could be a function that applies the template:
function getTemplateString (videoId) {
return `https://player.vimeo.com/video/${videoId}?api=1`
}
Note that the back-tick quotes are nested in regular quotes.
const VIMEO_EMBED_URL = "`https://player.vimeo.com/video/${videoId}?api=1`";
function getTemplateString() {
let videoId = 'qwerty';
return eval(VIMEO_EMBED_URL);
}
document.write(getTemplateString());
I understand that many uses of eval, probably including this one, are not recommended. (They introduce possible security concerns, etc.) However, eval IS part of the language, and some JavaScript experts do discuss how to use it on occasion.
This answer does address the issue raised in the question and does allow the coder to combine the convenient syntax of a template string and the permanence of storing it in a const. Just understand that it's "User beware".

Categories