Skip to content

Commit

Permalink
feat: add byEngine and toDesktop normalizers
Browse files Browse the repository at this point in the history
  • Loading branch information
ylemkimon committed Jul 29, 2020
1 parent efd7b93 commit 1c608b6
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 1 deletion.
7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -522,6 +522,13 @@ Options:
* `normalizers`: An array of names of normalizers below and functions
that accept a browser and return the normalized versions, which are
applied to resolved browsers in order. For instance, `['byEngine', 'toDesktop']`.
* `byEngine`: Normalize Chromium-based browsers to Chrome. For instance,
UC Browser, QQ Browser, Baidu browser for Android, and Samsung Internet
will return `and_chr` with the version of Chromium they are based on.
Note Edge and Opera is not normalized. Gecko-based browsers are
also normalized to Firefox, e.g., KaiOS Browser will return `and_ff`.
* `toDesktop`: Normalize mobile browsers to desktop browsers.
For instance, Browserslist will return `chrome 20` on `and_chr 20`

For non-JS environment and debug purpose you can use CLI tool:

Expand Down
63 changes: 62 additions & 1 deletion index.js
Expand Up @@ -9,6 +9,7 @@ var env = require('./node') // Will load browser.js in webpack

var YEAR = 365.259641 * 24 * 60 * 60 * 1000
var ANDROID_EVERGREEN_FIRST = 37
var ANDROID_CLASSIC_REGEX = /^(?:[2-4]\.|[34]$)/

var QUERY_OR = 1
var QUERY_AND = 2
Expand Down Expand Up @@ -265,7 +266,7 @@ function normalizeAndroidVersions (androidVersions, chromeVersions) {
var firstEvergreen = ANDROID_EVERGREEN_FIRST
var last = chromeVersions[chromeVersions.length - 1]
return androidVersions
.filter(function (version) { return /^(?:[2-4]\.|[34]$)/.test(version) })
.filter(function (version) { return ANDROID_CLASSIC_REGEX.test(version) })
.concat(chromeVersions.slice(firstEvergreen - last - 1))
}

Expand Down Expand Up @@ -563,6 +564,46 @@ browserslist.desktopNames = {
android: 'chrome' // has extra processing logic
}

// Tools such as compat-table only provides compatibility data for
// popular browsers. Fallback to Chrome for Chromium-based browsers
// and Firefox for Gecko-based browsers. A number indicates `and_chr`
browserslist.normalizedVersions = {
// From Samsung Internet release notes at
// https://developer.samsung.com/internet/release-note.html,
// Chrome version page (chrome://version), and the user agent string
// Also available at https://github.com/mdn/browser-compat-data/blob/master
// /browsers/samsunginternet_android.json
'samsung 4': 44,
'samsung 5': 51,
'samsung 6': 56,
'samsung 7': 59,
'samsung 8': 63,
'samsung 9': 67,
'samsung 10': 71,
'samsung 11': 75,
'samsung 12': 79,

// From Opera for Android release notes at
// https://forums.opera.com/category/20/opera-for-android
// Opera version page (opera://version), and the user agent string
// Also available at https://github.com/mdn/browser-compat-data/blob/master
// /browsers/opera_android.json
'op_mob 46': 63,

// From the kernel version at https://plus.ucweb.com/download/
// and the user agent string
'and_uc 12': 57,

// From https://browser.qq.com/ and the user agent string
'and_qq 10': 70,

// From the user agent string
'baidu 7': 48,

// From https://github.com/kaiostech/gecko-b2g and the user agent string
'kaios 2': 'and_ff 48'
}

// Aliases to work with joined versions like `ios_saf 7.0-7.1`
browserslist.versionAliases = { }

Expand Down Expand Up @@ -1161,6 +1202,26 @@ var QUERIES = [
]

var NORMALIZERS = {
byEngine: function (browser) {
var major = browser.split('.')[0]
var normalized = browserslist.normalizedVersions[major]
if (!normalized) {
return browser
} else if (typeof normalized === 'number') {
normalized = 'and_chr ' + normalized
}
return normalized
},
toDesktop: function (browser) {
browser = browser.split(' ')
var name = browser[0]
var version = browser[1]
if (browserslist.desktopNames[name] &&
!(name === 'android' && ANDROID_CLASSIC_REGEX.test(version))) {
name = browserslist.desktopNames[name]
}
return name + ' ' + version
}
};

// Get and convert Can I Use data
Expand Down
35 changes: 35 additions & 0 deletions test/normalizer.test.js
@@ -1,6 +1,7 @@
let browserslist = require('../')

let originData = browserslist.data
let originNormalizedVersions = browserslist.normalizedVersions

beforeEach(() => {
browserslist.data = {
Expand All @@ -25,10 +26,44 @@ beforeEach(() => {
versions: ['83']
}
}

browserslist.normalizedVersions = {
'samsung 4': 44,
'kaios 2': 'and_ff 48'
}
})

afterEach(() => {
browserslist.data = originData
browserslist.normalizedVersions = originNormalizedVersions
})

it('normalizes mobile browsers to desktop browsers', () => {
let opts = { normalizers: ['toDesktop'] }
expect(browserslist('android 37', opts)).toEqual(['chrome 37'])
expect(browserslist('last 1 and_chr versions', opts)).toEqual(['chrome 83'])
expect(browserslist('samsung 4', opts)).toEqual(['samsung 4'])
})

it('does not normalize classic Android webview versions', () => {
let opts = { normalizers: ['toDesktop'] }
expect(browserslist('android 4.4-37', opts)).toEqual([
'android 4.4.3-4.4.4', 'android 4.4', 'chrome 37'
])
})

it('normalizes Chromium-based browsers to Chrome', () => {
let opts = { normalizers: ['byEngine'] }
expect(browserslist('samsung 4', opts)).toEqual(['and_chr 44'])
expect(browserslist('kaios 2.5', opts)).toEqual(['and_ff 48'])
expect(browserslist('and_chr 83', opts)).toEqual(['and_chr 83'])
})

it('should apply each normalizer in order', () => {
let opts = { normalizers: ['byEngine', 'toDesktop'] }
expect(browserslist('samsung 4', opts)).toEqual(['chrome 44'])
expect(browserslist('kaios 2.5', opts)).toEqual(['firefox 48'])
expect(browserslist('and_chr 83', opts)).toEqual(['chrome 83'])
})

it('accepts a normalizer function', () => {
Expand Down

0 comments on commit 1c608b6

Please sign in to comment.