Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for getUnsupportedUserAgentRegex() #1558

Open
1 task
oprypkhantc opened this issue Dec 16, 2024 · 1 comment
Open
1 task

Support for getUnsupportedUserAgentRegex() #1558

oprypkhantc opened this issue Dec 16, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@oprypkhantc
Copy link

Would you like to work on this feature?

  • Check this if you would like to implement a PR, we are more than happy to help you go through the process.

What problem are you trying to solve?

Hey.

Currently the generated regex by getUserAgentRegex outputs a RegExp to match a browser that is supported. This works for build/automation tools - they can use that information to avoid unnecessary transformations when features are natively supported.

However, this works poorly to match a browser that is not supported. Suppose we have this example .browserlistrc:

chrome >= 85
firefox >= 76
safari >= 14.1
not ie

If we then simply take the result of the browserslist-useragent-regexp --allowHigherVersions and do this:

import supportedBrowsers from './supportedBrowsers.js';

if (navigator.userAgent && !supportedBrowsers.test(navigator.userAgent)) {
    window.location.href = '/old-browser.html';
}

then indeed Chrome < 85, Firefox < 76 and Safari < 14.1 will be redirected to /old-browser.html. The problem with this approach is that any other browser, say latest Opera or any new (unknown to Browserslist) browser, will also be redirected to /old-browser.html, even though it may indeed be working and fully functional.

Describe the solution you'd like

A new getUnsupportedUserAgentRegex() function that returns a RegExp matching all browsers that were specified in .browserslistrc, but whose version does not match, including negated ones (not ie).

Basically, the same .browserslistrc from above:

chrome >= 85
firefox >= 76
safari >= 14.1
not ie

would match Chrome < 85, Firefox < 76, Safari <14.1 and Internet Explorer, but NOT any other browser that wasn't explicitly specified in .browserslistrc. So Chrome >= 85, Firefox >= 76, Safari >= 14.1, Opera >= 0, Baidu >= 0 etc.


I would work on the PR for this, but I'm not sure how to approach this since browserslist() function doesn't even return Internet Explorer as one of the browser in this case. It seems that this must first be implemented on browserslist side by negating each expression separately, transforming the original file:

not chrome >= 85
not firefox >= 76
not safari >= 14.1
not not ie

Which would then give us basically what I want:

chrome < 85
firefox < 76
safari < 14.1
ie

Describe alternatives you've considered

I've considered using two RegExps:

import { getUserAgentRegexes } from 'browserslist-useragent-regexp';

const browserRegexes = getUserAgentRegexes({
	allowHigherVersions: true,
});
// Browsers that were explicitly specified in the config, e.g. Firefox, Chrome and Safari
const knownBrowsers = new RegExp(browserRegexes.map(({ sourceRegex}) => sourceRegex.source).join('|'));

// Same browsers, but also with version constraints
const supportedBrowsers = new RegExp(browserRegexes.map(({ regex}) => regex.source).join('|'));

if (navigator.userAgent && knownBrowsers.test(navigator.userAgent) && !supportedBrowsers.test(navigator.userAgent)) {
    window.location.href = '/old-browser.html';
}

This does fix the problem of unknown browsers - those not explicitly specified (e.g. Opera from the example above) in the config will not be redirected anymore.

But now explicitly NOT supported browsers will not be redirected to, because not ie is completely ignored and isn't present in any of the RegExps. So even though IE is explicitly specified as not supported, it won't be redirected.

Documentation, Adoption, Migration Strategy

Users can switch the function to a new one, or use a new CLI flag (browserslist-useragent-regexp --unsupported).

// browserslist-useragent-regexp --allowHigherVersions --unsupported
import unsupportedBrowsers from './unsupportedBrowsers.js';

if (navigator.userAgent && unsupportedBrowsers.test(navigator.userAgent)) {
    window.location.href = '/old-browser.html';
}
@oprypkhantc oprypkhantc added the enhancement New feature or request label Dec 16, 2024
@oprypkhantc
Copy link
Author

Another workaround currently is crafting a separate .browserslistrc.unsupported containing negated conditions from the "main" .browserslistrc:

chrome < 85
firefox < 76
safari < 14.1
ie

This does work, but obviously is not ideal as the information is duplicated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant