@tinkoff/user-agent 0.7.204 → 0.8.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -1
- package/lib/client-hints/constants.d.ts +7 -0
- package/lib/client-hints/constants.es.js +23 -0
- package/lib/client-hints/constants.js +32 -0
- package/lib/client-hints/parse-client-hints-headers/consts.d.ts +11 -0
- package/lib/client-hints/parse-client-hints-headers/consts.es.js +11 -0
- package/lib/client-hints/parse-client-hints-headers/consts.js +15 -0
- package/lib/client-hints/parse-client-hints-headers/parseClientHintsHeaders.d.ts +18 -0
- package/lib/client-hints/parse-client-hints-headers/parseClientHintsHeaders.es.js +54 -0
- package/lib/client-hints/parse-client-hints-headers/parseClientHintsHeaders.js +58 -0
- package/lib/client-hints/parse-client-hints-user-agent-data/parseClientHintsUserAgentData.d.ts +17 -0
- package/lib/client-hints/parse-client-hints-user-agent-data/parseClientHintsUserAgentData.es.js +47 -0
- package/lib/client-hints/parse-client-hints-user-agent-data/parseClientHintsUserAgentData.js +51 -0
- package/lib/client-hints/utils/getBackwardCompatibleOsName.d.ts +2 -0
- package/lib/client-hints/utils/getBackwardCompatibleOsName.es.js +10 -0
- package/lib/client-hints/utils/getBackwardCompatibleOsName.js +14 -0
- package/lib/client-hints/utils/parseBrowserFromString.d.ts +6 -0
- package/lib/client-hints/utils/parseBrowserFromString.es.js +42 -0
- package/lib/client-hints/utils/parseBrowserFromString.js +46 -0
- package/lib/client-hints/utils/parseBrowserFromUserAgentData.d.ts +6 -0
- package/lib/client-hints/utils/parseBrowserFromUserAgentData.es.js +39 -0
- package/lib/client-hints/utils/parseBrowserFromUserAgentData.js +43 -0
- package/lib/client-hints/utils/parseQuotedString.d.ts +2 -0
- package/lib/client-hints/utils/parseQuotedString.es.js +18 -0
- package/lib/client-hints/utils/parseQuotedString.js +22 -0
- package/lib/constants.d.ts +15 -7
- package/lib/constants.es.js +16 -81
- package/lib/constants.js +18 -87
- package/lib/index.d.ts +7 -5
- package/lib/index.es.js +5 -3
- package/lib/index.js +12 -8
- package/lib/parse-user-agent-header/consts.d.ts +2 -0
- package/lib/parse-user-agent-header/consts.es.js +27 -0
- package/lib/parse-user-agent-header/consts.js +31 -0
- package/lib/{userAgent.d.ts → parse-user-agent-header/parseUserAgentHeader.d.ts} +2 -2
- package/lib/{userAgent.es.js → parse-user-agent-header/parseUserAgentHeader.es.js} +7 -9
- package/lib/parse-user-agent-header/parseUserAgentHeader.js +35 -0
- package/lib/{isSameSiteNoneCompatible.es.js → parse-user-agent-header/utils/is-same-site-none-compatible/isSameSiteNoneCompatible.es.js} +6 -1
- package/lib/{isSameSiteNoneCompatible.js → parse-user-agent-header/utils/is-same-site-none-compatible/isSameSiteNoneCompatible.js} +6 -1
- package/lib/{utils/merge-extensions.d.ts → parse-user-agent-header/utils/mergeExtensions.d.ts} +2 -2
- package/lib/{utils/merge-extensions.es.js → parse-user-agent-header/utils/mergeExtensions.es.js} +1 -1
- package/lib/{utils/merge-extensions.js → parse-user-agent-header/utils/mergeExtensions.js} +3 -3
- package/lib/parse-user-agent-header/utils/toLowerName.d.ts +2 -0
- package/lib/parse-user-agent-header/utils/toLowerName.es.js +14 -0
- package/lib/parse-user-agent-header/utils/toLowerName.js +24 -0
- package/lib/satisfies/constants.d.ts +16 -0
- package/lib/satisfies/constants.es.js +75 -0
- package/lib/satisfies/constants.js +82 -0
- package/lib/satisfies/is-browser-satisfies-requirements.d.ts +4 -0
- package/lib/satisfies/is-browser-satisfies-requirements.es.js +74 -0
- package/lib/satisfies/is-browser-satisfies-requirements.js +84 -0
- package/lib/satisfies/types.d.ts +6 -0
- package/lib/satisfies/utils/normalizeBrowserslist.d.ts +3 -0
- package/lib/satisfies/utils/normalizeBrowserslist.es.js +42 -0
- package/lib/satisfies/utils/normalizeBrowserslist.js +50 -0
- package/lib/types.d.ts +4 -0
- package/lib/utils/getBrowserEngine.d.ts +9 -0
- package/lib/utils/{get-browser-engine.es.js → getBrowserEngine.es.js} +13 -4
- package/lib/utils/{get-browser-engine.js → getBrowserEngine.js} +13 -4
- package/lib/utils/getMobileOs.d.ts +9 -0
- package/lib/utils/getMobileOs.es.js +24 -0
- package/lib/utils/getMobileOs.js +28 -0
- package/package.json +3 -3
- package/lib/client-hints.d.ts +0 -33
- package/lib/client-hints.es.js +0 -178
- package/lib/client-hints.js +0 -183
- package/lib/satisfies.d.ts +0 -8
- package/lib/satisfies.es.js +0 -107
- package/lib/satisfies.js +0 -118
- package/lib/userAgent.js +0 -43
- package/lib/utils/get-browser-engine.d.ts +0 -2
- package/lib/utils/get-mobile-os.d.ts +0 -2
- package/lib/utils/get-mobile-os.es.js +0 -15
- package/lib/utils/get-mobile-os.js +0 -19
- /package/lib/{isSameSiteNoneCompatible.d.ts → parse-user-agent-header/utils/is-same-site-none-compatible/isSameSiteNoneCompatible.d.ts} +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/bots.txt +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/not_supported.txt +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/not_supported_modern.txt +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/supported.txt +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/supported_force.txt +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/supported_modern.txt +0 -0
- /package/lib/{__tests__ → satisfies/__tests__}/uaDatasets/unknown.txt +0 -0
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var consts = require('../consts.js');
|
|
6
6
|
|
|
7
7
|
const mergeExtensions = (extensions) => {
|
|
8
8
|
if (!extensions?.length) {
|
|
9
9
|
return {
|
|
10
|
-
browser: [...
|
|
10
|
+
browser: [...consts.uaParserExtensions],
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
const merged = extensions.reduce((acc, curr) => ({
|
|
@@ -18,7 +18,7 @@ const mergeExtensions = (extensions) => {
|
|
|
18
18
|
}), {});
|
|
19
19
|
return {
|
|
20
20
|
...merged,
|
|
21
|
-
browser: [...(merged.browser || []), ...
|
|
21
|
+
browser: [...(merged.browser || []), ...consts.uaParserExtensions],
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import propOr from '@tinkoff/utils/object/propOr';
|
|
2
|
+
import compose from '@tinkoff/utils/function/compose';
|
|
3
|
+
import toLower from '@tinkoff/utils/string/toLower';
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
Function toLowerName returns the name property of an object in lowercase or an empty string if name is not present.
|
|
7
|
+
|
|
8
|
+
toLowerName(anyObj)
|
|
9
|
+
equivalent to
|
|
10
|
+
(anyObj.name || '')?.toLowerCase()
|
|
11
|
+
*/
|
|
12
|
+
const toLowerName = compose(toLower, propOr('name', ''));
|
|
13
|
+
|
|
14
|
+
export { toLowerName };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var propOr = require('@tinkoff/utils/object/propOr');
|
|
6
|
+
var compose = require('@tinkoff/utils/function/compose');
|
|
7
|
+
var toLower = require('@tinkoff/utils/string/toLower');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
var propOr__default = /*#__PURE__*/_interopDefaultLegacy(propOr);
|
|
12
|
+
var compose__default = /*#__PURE__*/_interopDefaultLegacy(compose);
|
|
13
|
+
var toLower__default = /*#__PURE__*/_interopDefaultLegacy(toLower);
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
Function toLowerName returns the name property of an object in lowercase or an empty string if name is not present.
|
|
17
|
+
|
|
18
|
+
toLowerName(anyObj)
|
|
19
|
+
equivalent to
|
|
20
|
+
(anyObj.name || '')?.toLowerCase()
|
|
21
|
+
*/
|
|
22
|
+
const toLowerName = compose__default["default"](toLower__default["default"], propOr__default["default"]('name', ''));
|
|
23
|
+
|
|
24
|
+
exports.toLowerName = toLowerName;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DeviceType as DeviceTypeType } from '../types';
|
|
2
|
+
export declare const BROWSERS_LIST_MAP: {
|
|
3
|
+
[key: string]: {
|
|
4
|
+
type: DeviceTypeType | 'any';
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export declare const CHROMIUM_BASED_BROWSERS: string[];
|
|
9
|
+
export declare const DEVICE_TYPES: Record<string, string>;
|
|
10
|
+
export declare const BROWSERS_WITHOUT_COMPLETE_STAT: {
|
|
11
|
+
Samsung: string;
|
|
12
|
+
Android: string;
|
|
13
|
+
UCAndroid: string;
|
|
14
|
+
OperaMobile: string;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DeviceType } from '../constants.es.js';
|
|
2
|
+
|
|
3
|
+
const BROWSERS_LIST_MAP = {
|
|
4
|
+
chrome: {
|
|
5
|
+
type: DeviceType.desktop,
|
|
6
|
+
name: 'chrome',
|
|
7
|
+
},
|
|
8
|
+
safari: {
|
|
9
|
+
type: DeviceType.desktop,
|
|
10
|
+
name: 'safari',
|
|
11
|
+
},
|
|
12
|
+
firefox: {
|
|
13
|
+
type: DeviceType.desktop,
|
|
14
|
+
name: 'firefox',
|
|
15
|
+
},
|
|
16
|
+
opera: {
|
|
17
|
+
type: DeviceType.desktop,
|
|
18
|
+
name: 'opera',
|
|
19
|
+
},
|
|
20
|
+
ie: {
|
|
21
|
+
type: DeviceType.desktop,
|
|
22
|
+
name: 'ie',
|
|
23
|
+
},
|
|
24
|
+
edge: {
|
|
25
|
+
type: 'any',
|
|
26
|
+
name: 'edge',
|
|
27
|
+
},
|
|
28
|
+
and_chr: {
|
|
29
|
+
type: DeviceType.mobile,
|
|
30
|
+
name: 'chrome',
|
|
31
|
+
},
|
|
32
|
+
ios_saf: {
|
|
33
|
+
type: DeviceType.mobile,
|
|
34
|
+
name: 'mobile safari',
|
|
35
|
+
},
|
|
36
|
+
android: {
|
|
37
|
+
type: DeviceType.mobile,
|
|
38
|
+
name: 'android browser',
|
|
39
|
+
},
|
|
40
|
+
op_mob: {
|
|
41
|
+
type: DeviceType.mobile,
|
|
42
|
+
name: 'opera',
|
|
43
|
+
},
|
|
44
|
+
and_uc: {
|
|
45
|
+
type: DeviceType.mobile,
|
|
46
|
+
name: 'ucbrowser',
|
|
47
|
+
},
|
|
48
|
+
and_ff: {
|
|
49
|
+
type: DeviceType.mobile,
|
|
50
|
+
name: 'firefox',
|
|
51
|
+
},
|
|
52
|
+
samsung: {
|
|
53
|
+
type: DeviceType.mobile,
|
|
54
|
+
name: 'samsung browser',
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const CHROMIUM_BASED_BROWSERS = [
|
|
58
|
+
'android browser',
|
|
59
|
+
'yandex',
|
|
60
|
+
'blink',
|
|
61
|
+
'vivaldi' /* , 'chrome webview', 'opera', 'samsung' */,
|
|
62
|
+
];
|
|
63
|
+
const DEVICE_TYPES = {
|
|
64
|
+
mobile: DeviceType.mobile,
|
|
65
|
+
tablet: DeviceType.mobile,
|
|
66
|
+
desktop: DeviceType.desktop,
|
|
67
|
+
};
|
|
68
|
+
const BROWSERS_WITHOUT_COMPLETE_STAT = {
|
|
69
|
+
Samsung: 'samsung',
|
|
70
|
+
Android: 'android',
|
|
71
|
+
UCAndroid: 'and_uc',
|
|
72
|
+
OperaMobile: 'op_mob',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export { BROWSERS_LIST_MAP, BROWSERS_WITHOUT_COMPLETE_STAT, CHROMIUM_BASED_BROWSERS, DEVICE_TYPES };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var constants = require('../constants.js');
|
|
6
|
+
|
|
7
|
+
const BROWSERS_LIST_MAP = {
|
|
8
|
+
chrome: {
|
|
9
|
+
type: constants.DeviceType.desktop,
|
|
10
|
+
name: 'chrome',
|
|
11
|
+
},
|
|
12
|
+
safari: {
|
|
13
|
+
type: constants.DeviceType.desktop,
|
|
14
|
+
name: 'safari',
|
|
15
|
+
},
|
|
16
|
+
firefox: {
|
|
17
|
+
type: constants.DeviceType.desktop,
|
|
18
|
+
name: 'firefox',
|
|
19
|
+
},
|
|
20
|
+
opera: {
|
|
21
|
+
type: constants.DeviceType.desktop,
|
|
22
|
+
name: 'opera',
|
|
23
|
+
},
|
|
24
|
+
ie: {
|
|
25
|
+
type: constants.DeviceType.desktop,
|
|
26
|
+
name: 'ie',
|
|
27
|
+
},
|
|
28
|
+
edge: {
|
|
29
|
+
type: 'any',
|
|
30
|
+
name: 'edge',
|
|
31
|
+
},
|
|
32
|
+
and_chr: {
|
|
33
|
+
type: constants.DeviceType.mobile,
|
|
34
|
+
name: 'chrome',
|
|
35
|
+
},
|
|
36
|
+
ios_saf: {
|
|
37
|
+
type: constants.DeviceType.mobile,
|
|
38
|
+
name: 'mobile safari',
|
|
39
|
+
},
|
|
40
|
+
android: {
|
|
41
|
+
type: constants.DeviceType.mobile,
|
|
42
|
+
name: 'android browser',
|
|
43
|
+
},
|
|
44
|
+
op_mob: {
|
|
45
|
+
type: constants.DeviceType.mobile,
|
|
46
|
+
name: 'opera',
|
|
47
|
+
},
|
|
48
|
+
and_uc: {
|
|
49
|
+
type: constants.DeviceType.mobile,
|
|
50
|
+
name: 'ucbrowser',
|
|
51
|
+
},
|
|
52
|
+
and_ff: {
|
|
53
|
+
type: constants.DeviceType.mobile,
|
|
54
|
+
name: 'firefox',
|
|
55
|
+
},
|
|
56
|
+
samsung: {
|
|
57
|
+
type: constants.DeviceType.mobile,
|
|
58
|
+
name: 'samsung browser',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const CHROMIUM_BASED_BROWSERS = [
|
|
62
|
+
'android browser',
|
|
63
|
+
'yandex',
|
|
64
|
+
'blink',
|
|
65
|
+
'vivaldi' /* , 'chrome webview', 'opera', 'samsung' */,
|
|
66
|
+
];
|
|
67
|
+
const DEVICE_TYPES = {
|
|
68
|
+
mobile: constants.DeviceType.mobile,
|
|
69
|
+
tablet: constants.DeviceType.mobile,
|
|
70
|
+
desktop: constants.DeviceType.desktop,
|
|
71
|
+
};
|
|
72
|
+
const BROWSERS_WITHOUT_COMPLETE_STAT = {
|
|
73
|
+
Samsung: 'samsung',
|
|
74
|
+
Android: 'android',
|
|
75
|
+
UCAndroid: 'and_uc',
|
|
76
|
+
OperaMobile: 'op_mob',
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
exports.BROWSERS_LIST_MAP = BROWSERS_LIST_MAP;
|
|
80
|
+
exports.BROWSERS_WITHOUT_COMPLETE_STAT = BROWSERS_WITHOUT_COMPLETE_STAT;
|
|
81
|
+
exports.CHROMIUM_BASED_BROWSERS = CHROMIUM_BASED_BROWSERS;
|
|
82
|
+
exports.DEVICE_TYPES = DEVICE_TYPES;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { UserAgent } from '../types';
|
|
2
|
+
import type { SatisfiesOptions } from './types';
|
|
3
|
+
export declare const isBrowserSatisfiesRequirements: (userAgent: UserAgent | string, browserslistConfig?: string[], { env, forceMinimumUnknownVersions }?: SatisfiesOptions) => boolean | null;
|
|
4
|
+
//# sourceMappingURL=is-browser-satisfies-requirements.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import isString from '@tinkoff/utils/is/string';
|
|
2
|
+
import browserslistTinkoffConfig from '@tinkoff/browserslist-config';
|
|
3
|
+
import browserslistFileConfig from '@tramvai/cli/lib/external/browserslist-normalized-file-config';
|
|
4
|
+
import { parseUserAgentHeader } from '../parse-user-agent-header/parseUserAgentHeader.es.js';
|
|
5
|
+
import { CHROMIUM_BASED_BROWSERS, BROWSERS_WITHOUT_COMPLETE_STAT, DEVICE_TYPES, BROWSERS_LIST_MAP } from './constants.es.js';
|
|
6
|
+
import { normalizeBrowserslist } from './utils/normalizeBrowserslist.es.js';
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
The function isBrowserSatisfiesRequirements checks if a given user agent satisfies the specified
|
|
10
|
+
browser requirements based on a browserslist configuration. It parses the user agent to determine
|
|
11
|
+
the browser and its version, normalizes the browserslist configuration, and compares the browser
|
|
12
|
+
version against the specified requirements. The function returns true if the browser meets the requirements,
|
|
13
|
+
false if it does not, and null if the browser is not found in the browserslist.
|
|
14
|
+
It also handles special cases for Chromium-based browsers and allows forcing the use of minimum requested
|
|
15
|
+
versions for browsers with incomplete statistics.
|
|
16
|
+
*/
|
|
17
|
+
const isBrowserSatisfiesRequirements = (userAgent, browserslistConfig, { env = 'defaults', forceMinimumUnknownVersions = false } = {}) => {
|
|
18
|
+
const ua = isString(userAgent) ? parseUserAgentHeader(userAgent) : userAgent;
|
|
19
|
+
const { engine: { name: engineName = '', version: engineVersion }, device: { type = '' } = {}, } = ua;
|
|
20
|
+
let { browser: { name: browserName = '', version: browserVersion = '' } = {} } = ua;
|
|
21
|
+
/*
|
|
22
|
+
Chromium based browsers (yandex, samsung, opera, vivaldi, edge) specify the engine version as `Chrome/*'.
|
|
23
|
+
And the engine version (blink) will be converted to the chromium version one-to-one.
|
|
24
|
+
https://github.com/faisalman/ua-parser-js/pull/390
|
|
25
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#Rendering_engine
|
|
26
|
+
*/
|
|
27
|
+
if (engineName === 'chromium' ||
|
|
28
|
+
(engineName.toLowerCase() === 'blink' &&
|
|
29
|
+
CHROMIUM_BASED_BROWSERS.indexOf(browserName.toLowerCase()) !== -1)) {
|
|
30
|
+
browserName = 'chrome';
|
|
31
|
+
browserVersion = engineVersion || '';
|
|
32
|
+
}
|
|
33
|
+
// parseFloat - it will take away the major + minor versions, discard the rest.
|
|
34
|
+
const checkVersion = parseFloat(browserVersion);
|
|
35
|
+
const deviceType = DEVICE_TYPES[type] || type || DEVICE_TYPES.desktop; // по умолчанию считаем устройство десктопом
|
|
36
|
+
if (!browserName) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const targets = browserslistConfig ?? browserslistFileConfig[env] ?? browserslistTinkoffConfig[env];
|
|
40
|
+
const browsers = normalizeBrowserslist(targets);
|
|
41
|
+
// Browsers from query may not be present in https://caniuse.com/usage-table, and browserslist will return higher versions than requested.
|
|
42
|
+
// Example of this problem - https://github.com/babel/babel/issues/8545
|
|
43
|
+
// It is mean, that for this unknown versions babel will not add specific transforms, but still, transpiled code has a chance to work in required old browsers.
|
|
44
|
+
// And if `satisfies` will be used for example for old browser detection, we can force use minimum requested versions instead of minimum from caniuse data.
|
|
45
|
+
if (forceMinimumUnknownVersions) {
|
|
46
|
+
Object.keys(BROWSERS_WITHOUT_COMPLETE_STAT).forEach((browser) => {
|
|
47
|
+
const target = targets.find((query) => query.startsWith(browser));
|
|
48
|
+
// @todo - respect other browserslist query patterns
|
|
49
|
+
if (target && target.includes('>=')) {
|
|
50
|
+
const [targetBrowser, targetMinVersion] = target.split(' >= ');
|
|
51
|
+
// @ts-expect-error
|
|
52
|
+
const browserKey = BROWSERS_WITHOUT_COMPLETE_STAT[targetBrowser];
|
|
53
|
+
const mappedBrowser = BROWSERS_LIST_MAP[browserKey];
|
|
54
|
+
if (mappedBrowser && browsers[mappedBrowser.name]) {
|
|
55
|
+
if (Number(targetMinVersion) < Number(browsers[mappedBrowser.name][mappedBrowser.type])) {
|
|
56
|
+
browsers[mappedBrowser.name][mappedBrowser.type] = Number(targetMinVersion);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
let hasEntry = false;
|
|
63
|
+
if (browserName in browsers) {
|
|
64
|
+
const browserInfo = browsers[browserName];
|
|
65
|
+
const browserInfoVersion = browserInfo.any ?? browserInfo[deviceType];
|
|
66
|
+
hasEntry = !!browserInfoVersion;
|
|
67
|
+
if (checkVersion >= browserInfoVersion) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return hasEntry ? false : null; // null means that we did not find a browser match in the browserslist.
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export { isBrowserSatisfiesRequirements };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var isString = require('@tinkoff/utils/is/string');
|
|
6
|
+
var browserslistTinkoffConfig = require('@tinkoff/browserslist-config');
|
|
7
|
+
var browserslistFileConfig = require('@tramvai/cli/lib/external/browserslist-normalized-file-config');
|
|
8
|
+
var parseUserAgentHeader = require('../parse-user-agent-header/parseUserAgentHeader.js');
|
|
9
|
+
var constants = require('./constants.js');
|
|
10
|
+
var normalizeBrowserslist = require('./utils/normalizeBrowserslist.js');
|
|
11
|
+
|
|
12
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
|
+
|
|
14
|
+
var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
|
|
15
|
+
var browserslistTinkoffConfig__default = /*#__PURE__*/_interopDefaultLegacy(browserslistTinkoffConfig);
|
|
16
|
+
var browserslistFileConfig__default = /*#__PURE__*/_interopDefaultLegacy(browserslistFileConfig);
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
The function isBrowserSatisfiesRequirements checks if a given user agent satisfies the specified
|
|
20
|
+
browser requirements based on a browserslist configuration. It parses the user agent to determine
|
|
21
|
+
the browser and its version, normalizes the browserslist configuration, and compares the browser
|
|
22
|
+
version against the specified requirements. The function returns true if the browser meets the requirements,
|
|
23
|
+
false if it does not, and null if the browser is not found in the browserslist.
|
|
24
|
+
It also handles special cases for Chromium-based browsers and allows forcing the use of minimum requested
|
|
25
|
+
versions for browsers with incomplete statistics.
|
|
26
|
+
*/
|
|
27
|
+
const isBrowserSatisfiesRequirements = (userAgent, browserslistConfig, { env = 'defaults', forceMinimumUnknownVersions = false } = {}) => {
|
|
28
|
+
const ua = isString__default["default"](userAgent) ? parseUserAgentHeader.parseUserAgentHeader(userAgent) : userAgent;
|
|
29
|
+
const { engine: { name: engineName = '', version: engineVersion }, device: { type = '' } = {}, } = ua;
|
|
30
|
+
let { browser: { name: browserName = '', version: browserVersion = '' } = {} } = ua;
|
|
31
|
+
/*
|
|
32
|
+
Chromium based browsers (yandex, samsung, opera, vivaldi, edge) specify the engine version as `Chrome/*'.
|
|
33
|
+
And the engine version (blink) will be converted to the chromium version one-to-one.
|
|
34
|
+
https://github.com/faisalman/ua-parser-js/pull/390
|
|
35
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#Rendering_engine
|
|
36
|
+
*/
|
|
37
|
+
if (engineName === 'chromium' ||
|
|
38
|
+
(engineName.toLowerCase() === 'blink' &&
|
|
39
|
+
constants.CHROMIUM_BASED_BROWSERS.indexOf(browserName.toLowerCase()) !== -1)) {
|
|
40
|
+
browserName = 'chrome';
|
|
41
|
+
browserVersion = engineVersion || '';
|
|
42
|
+
}
|
|
43
|
+
// parseFloat - it will take away the major + minor versions, discard the rest.
|
|
44
|
+
const checkVersion = parseFloat(browserVersion);
|
|
45
|
+
const deviceType = constants.DEVICE_TYPES[type] || type || constants.DEVICE_TYPES.desktop; // по умолчанию считаем устройство десктопом
|
|
46
|
+
if (!browserName) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const targets = browserslistConfig ?? browserslistFileConfig__default["default"][env] ?? browserslistTinkoffConfig__default["default"][env];
|
|
50
|
+
const browsers = normalizeBrowserslist.normalizeBrowserslist(targets);
|
|
51
|
+
// Browsers from query may not be present in https://caniuse.com/usage-table, and browserslist will return higher versions than requested.
|
|
52
|
+
// Example of this problem - https://github.com/babel/babel/issues/8545
|
|
53
|
+
// It is mean, that for this unknown versions babel will not add specific transforms, but still, transpiled code has a chance to work in required old browsers.
|
|
54
|
+
// And if `satisfies` will be used for example for old browser detection, we can force use minimum requested versions instead of minimum from caniuse data.
|
|
55
|
+
if (forceMinimumUnknownVersions) {
|
|
56
|
+
Object.keys(constants.BROWSERS_WITHOUT_COMPLETE_STAT).forEach((browser) => {
|
|
57
|
+
const target = targets.find((query) => query.startsWith(browser));
|
|
58
|
+
// @todo - respect other browserslist query patterns
|
|
59
|
+
if (target && target.includes('>=')) {
|
|
60
|
+
const [targetBrowser, targetMinVersion] = target.split(' >= ');
|
|
61
|
+
// @ts-expect-error
|
|
62
|
+
const browserKey = constants.BROWSERS_WITHOUT_COMPLETE_STAT[targetBrowser];
|
|
63
|
+
const mappedBrowser = constants.BROWSERS_LIST_MAP[browserKey];
|
|
64
|
+
if (mappedBrowser && browsers[mappedBrowser.name]) {
|
|
65
|
+
if (Number(targetMinVersion) < Number(browsers[mappedBrowser.name][mappedBrowser.type])) {
|
|
66
|
+
browsers[mappedBrowser.name][mappedBrowser.type] = Number(targetMinVersion);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
let hasEntry = false;
|
|
73
|
+
if (browserName in browsers) {
|
|
74
|
+
const browserInfo = browsers[browserName];
|
|
75
|
+
const browserInfoVersion = browserInfo.any ?? browserInfo[deviceType];
|
|
76
|
+
hasEntry = !!browserInfoVersion;
|
|
77
|
+
if (checkVersion >= browserInfoVersion) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return hasEntry ? false : null; // null means that we did not find a browser match in the browserslist.
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
exports.isBrowserSatisfiesRequirements = isBrowserSatisfiesRequirements;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import browserslist from 'browserslist';
|
|
2
|
+
import { BROWSERS_LIST_MAP } from '../constants.es.js';
|
|
3
|
+
|
|
4
|
+
const normalizeBrowserslist = (query) => {
|
|
5
|
+
const resolved = browserslist(query, {
|
|
6
|
+
/*
|
|
7
|
+
We set it to true so that the browserslist returns the full list for mobile browsers,
|
|
8
|
+
because by default, due to the fact that `Can I use` stores only the latest version of mobile browsers,
|
|
9
|
+
the browserslist returns only the latest version for mobile devices,
|
|
10
|
+
and so it will map compliance to the desktop version.
|
|
11
|
+
*/
|
|
12
|
+
mobileToDesktop: true,
|
|
13
|
+
})
|
|
14
|
+
/*
|
|
15
|
+
Since ie was removed from the @tinkoff/browserslist-config config, in order to cut off ie,
|
|
16
|
+
we add a dummy version so that the entire function returns false for any version of ie,
|
|
17
|
+
and if the regular ie version was set in the custom config or in the config passed as an argument,
|
|
18
|
+
this dummy version will not affect anything and the custom version will be used.
|
|
19
|
+
*/
|
|
20
|
+
.concat(['ie 999']);
|
|
21
|
+
const result = {};
|
|
22
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
23
|
+
const [name, version] = resolved[i].split(' ');
|
|
24
|
+
if (BROWSERS_LIST_MAP[name]) {
|
|
25
|
+
const { type: mapType, name: mapName } = BROWSERS_LIST_MAP[name];
|
|
26
|
+
const mapVersion = parseFloat(version);
|
|
27
|
+
if (result[mapName]) {
|
|
28
|
+
if (!result[mapName][mapType] || result[mapName][mapType] > mapVersion) {
|
|
29
|
+
result[mapName][mapType] = mapVersion;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
result[mapName] = {
|
|
34
|
+
[mapType]: mapVersion,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { normalizeBrowserslist };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var browserslist = require('browserslist');
|
|
6
|
+
var constants = require('../constants.js');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
|
+
|
|
10
|
+
var browserslist__default = /*#__PURE__*/_interopDefaultLegacy(browserslist);
|
|
11
|
+
|
|
12
|
+
const normalizeBrowserslist = (query) => {
|
|
13
|
+
const resolved = browserslist__default["default"](query, {
|
|
14
|
+
/*
|
|
15
|
+
We set it to true so that the browserslist returns the full list for mobile browsers,
|
|
16
|
+
because by default, due to the fact that `Can I use` stores only the latest version of mobile browsers,
|
|
17
|
+
the browserslist returns only the latest version for mobile devices,
|
|
18
|
+
and so it will map compliance to the desktop version.
|
|
19
|
+
*/
|
|
20
|
+
mobileToDesktop: true,
|
|
21
|
+
})
|
|
22
|
+
/*
|
|
23
|
+
Since ie was removed from the @tinkoff/browserslist-config config, in order to cut off ie,
|
|
24
|
+
we add a dummy version so that the entire function returns false for any version of ie,
|
|
25
|
+
and if the regular ie version was set in the custom config or in the config passed as an argument,
|
|
26
|
+
this dummy version will not affect anything and the custom version will be used.
|
|
27
|
+
*/
|
|
28
|
+
.concat(['ie 999']);
|
|
29
|
+
const result = {};
|
|
30
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
31
|
+
const [name, version] = resolved[i].split(' ');
|
|
32
|
+
if (constants.BROWSERS_LIST_MAP[name]) {
|
|
33
|
+
const { type: mapType, name: mapName } = constants.BROWSERS_LIST_MAP[name];
|
|
34
|
+
const mapVersion = parseFloat(version);
|
|
35
|
+
if (result[mapName]) {
|
|
36
|
+
if (!result[mapName][mapType] || result[mapName][mapType] > mapVersion) {
|
|
37
|
+
result[mapName][mapType] = mapVersion;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
result[mapName] = {
|
|
42
|
+
[mapType]: mapVersion,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
exports.normalizeBrowserslist = normalizeBrowserslist;
|
package/lib/types.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { BrowserEngine, DeviceType, MobileOs } from './constants';
|
|
2
|
+
export type BrowserEngineType = (typeof BrowserEngine)[keyof typeof BrowserEngine];
|
|
1
3
|
export interface Browser {
|
|
2
4
|
name: string | undefined;
|
|
3
5
|
/**
|
|
@@ -18,6 +20,7 @@ export interface Engine {
|
|
|
18
20
|
name: string | undefined;
|
|
19
21
|
version: string | undefined;
|
|
20
22
|
}
|
|
23
|
+
export type DeviceType = (typeof DeviceType)[keyof typeof DeviceType];
|
|
21
24
|
export interface Device {
|
|
22
25
|
/**
|
|
23
26
|
* Device type may be undefined in various cases.
|
|
@@ -37,6 +40,7 @@ export interface OS {
|
|
|
37
40
|
export interface Cpu {
|
|
38
41
|
architecture: string | undefined;
|
|
39
42
|
}
|
|
43
|
+
export type MobileOs = (typeof MobileOs)[keyof typeof MobileOs];
|
|
40
44
|
export interface UserAgent {
|
|
41
45
|
browser: Browser;
|
|
42
46
|
engine: Engine;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Possible values :
|
|
3
|
+
* firefox, safari, chrome, other
|
|
4
|
+
*
|
|
5
|
+
* The return type here should be BrowserEngine, not string,
|
|
6
|
+
* but we are not changing it to maintain backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getBrowserEngine: (browserName?: string, engineName?: string) => string;
|
|
9
|
+
//# sourceMappingURL=getBrowserEngine.d.ts.map
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
+
import { BrowserEngine } from '../constants.es.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Possible values :
|
|
5
|
+
* firefox, safari, chrome, other
|
|
6
|
+
*
|
|
7
|
+
* The return type here should be BrowserEngine, not string,
|
|
8
|
+
* but we are not changing it to maintain backward compatibility.
|
|
9
|
+
*/
|
|
1
10
|
const getBrowserEngine = (browserName, engineName) => {
|
|
2
11
|
switch (true) {
|
|
3
12
|
case browserName === 'firefox':
|
|
4
|
-
return
|
|
13
|
+
return BrowserEngine.firefox;
|
|
5
14
|
// If an `engineName` is webkit, and it's not Safari,
|
|
6
15
|
// then define the `browserName` as `safari`, because all browsers
|
|
7
16
|
// on iOS use webkit. Also, we are not handling mobile Safari separately,
|
|
8
17
|
// as it webkit too. See https://en.wikipedia.org/wiki/WebKit
|
|
9
18
|
case browserName === 'safari' || browserName === 'mobile safari' || engineName === 'webkit':
|
|
10
|
-
return
|
|
19
|
+
return BrowserEngine.safari;
|
|
11
20
|
// We aren't using something like `browserName === 'chrome'` here,
|
|
12
21
|
// because there are a lot of browsers based on chromium.
|
|
13
22
|
case engineName === 'blink' || engineName === 'chromium':
|
|
14
|
-
return
|
|
23
|
+
return BrowserEngine.chrome;
|
|
15
24
|
}
|
|
16
|
-
return
|
|
25
|
+
return BrowserEngine.other;
|
|
17
26
|
};
|
|
18
27
|
|
|
19
28
|
export { getBrowserEngine };
|
|
@@ -2,22 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var constants = require('../constants.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Possible values :
|
|
9
|
+
* firefox, safari, chrome, other
|
|
10
|
+
*
|
|
11
|
+
* The return type here should be BrowserEngine, not string,
|
|
12
|
+
* but we are not changing it to maintain backward compatibility.
|
|
13
|
+
*/
|
|
5
14
|
const getBrowserEngine = (browserName, engineName) => {
|
|
6
15
|
switch (true) {
|
|
7
16
|
case browserName === 'firefox':
|
|
8
|
-
return
|
|
17
|
+
return constants.BrowserEngine.firefox;
|
|
9
18
|
// If an `engineName` is webkit, and it's not Safari,
|
|
10
19
|
// then define the `browserName` as `safari`, because all browsers
|
|
11
20
|
// on iOS use webkit. Also, we are not handling mobile Safari separately,
|
|
12
21
|
// as it webkit too. See https://en.wikipedia.org/wiki/WebKit
|
|
13
22
|
case browserName === 'safari' || browserName === 'mobile safari' || engineName === 'webkit':
|
|
14
|
-
return
|
|
23
|
+
return constants.BrowserEngine.safari;
|
|
15
24
|
// We aren't using something like `browserName === 'chrome'` here,
|
|
16
25
|
// because there are a lot of browsers based on chromium.
|
|
17
26
|
case engineName === 'blink' || engineName === 'chromium':
|
|
18
|
-
return
|
|
27
|
+
return constants.BrowserEngine.chrome;
|
|
19
28
|
}
|
|
20
|
-
return
|
|
29
|
+
return constants.BrowserEngine.other;
|
|
21
30
|
};
|
|
22
31
|
|
|
23
32
|
exports.getBrowserEngine = getBrowserEngine;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Possible values:
|
|
3
|
+
* winphone, android, ios, blackberry
|
|
4
|
+
*
|
|
5
|
+
* The return type here should be MobileOs, not string | undefined,
|
|
6
|
+
* but we are not changing it to maintain backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getMobileOs: (osName?: string) => string | undefined;
|
|
9
|
+
//# sourceMappingURL=getMobileOs.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MobileOs } from '../constants.es.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Possible values:
|
|
5
|
+
* winphone, android, ios, blackberry
|
|
6
|
+
*
|
|
7
|
+
* The return type here should be MobileOs, not string | undefined,
|
|
8
|
+
* but we are not changing it to maintain backward compatibility.
|
|
9
|
+
*/
|
|
10
|
+
const getMobileOs = (osName) => {
|
|
11
|
+
switch (osName) {
|
|
12
|
+
case 'Windows Phone':
|
|
13
|
+
return MobileOs.winphone;
|
|
14
|
+
case 'Android':
|
|
15
|
+
return MobileOs.android;
|
|
16
|
+
case 'iOS':
|
|
17
|
+
return MobileOs.ios;
|
|
18
|
+
case 'BlackBerry':
|
|
19
|
+
case 'RIM Tablet OS':
|
|
20
|
+
return MobileOs.blackberry;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { getMobileOs };
|