diff --git a/package.json b/package.json index 76c9288..784c55c 100755 --- a/package.json +++ b/package.json @@ -178,6 +178,11 @@ "import": "./src/main/ua-parser.mjs", "types": "./src/main/ua-parser.d.ts" }, + "./device-utils": { + "require": "./src/device-utils/ua-parser-device-utils.js", + "import": "./src/device-utils/ua-parser-device-utils.mjs", + "types": "./src/device-utils/ua-parser-device-utils.d.ts" + }, "./enums": { "require": "./src/enums/ua-parser-enums.js", "import": "./src/enums/ua-parser-enums.mjs", diff --git a/script/build-esm.js b/script/build-esm.js index 98f7ffb..9d6ab83 100755 --- a/script/build-esm.js +++ b/script/build-esm.js @@ -36,7 +36,14 @@ const modules = [ [/esversion\: 3/ig, 'esversion: 6'], [/\/[\/\s]+export[\s\S]+/ig,'export {UAParser};'] ] - },{ + }, + { + src : 'src/device-utils/ua-parser-device-utils.js', + dest :'src/device-utils/ua-parser-device-utils.mjs', + title : 'ua-parser-js/device-utils', + replacements : [] + }, + { src : 'src/enums/ua-parser-enums.js', dest :'src/enums/ua-parser-enums.mjs', title : 'ua-parser-js/enums', diff --git a/src/device-utils/ua-parser-device-utils.d.ts b/src/device-utils/ua-parser-device-utils.d.ts new file mode 100644 index 0000000..08a806d --- /dev/null +++ b/src/device-utils/ua-parser-device-utils.d.ts @@ -0,0 +1,19 @@ +// Type definitions for Device Utils submodule of UAParser.js v2.0.0 +// Project: https://github.com/faisalman/ua-parser-js +// Definitions by: Faisal Salman + +import type { IResult, IDevice } from "../main/ua-parser"; + +declare function isMobile(val: IResult | IDevice | string): boolean; +declare function isSmartTV(val: IResult | IDevice | string): boolean; +declare function isTablet(val: IResult | IDevice | string): boolean; +declare function isWearable(val: IResult | IDevice | string): boolean; +declare function isXR(val: IResult | IDevice | string): boolean; + +export { + isMobile, + isSmartTV, + isTablet, + isWearable, + isXR +}; diff --git a/src/device-utils/ua-parser-device-utils.js b/src/device-utils/ua-parser-device-utils.js new file mode 100644 index 0000000..fdfee9f --- /dev/null +++ b/src/device-utils/ua-parser-device-utils.js @@ -0,0 +1,36 @@ +////////////////////////////////////////////////// +/* Device Utils Submodule for UAParser.js v2.0.0 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +///////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +const UAParser = require('../main/ua-parser'); +const { Device: DeviceType } = require('../enums/ua-parser-enums'); + +const isDeviceType = (val, expectedType) => { + const uap = typeof val == 'string' ? UAParser(val) : val; // string + let actualType; + if (uap.hasOwnProperty('device')) { // IResult + actualType = uap.device?.type; + } else if (uap.hasOwnProperty('type')) { // IDevice + actualType = uap.type; + } + return actualType == expectedType; +}; + +const isMobile = val => isDeviceType(val, DeviceType.MOBILE); +const isSmartTV = val => isDeviceType(val, DeviceType.SMARTTV); +const isTablet = val => isDeviceType(val, DeviceType.TABLET); +const isWearable = val => isDeviceType(val, DeviceType.WEARABLE); +const isXR = val => isDeviceType(val, DeviceType.XR); + +module.exports = { + isMobile, + isSmartTV, + isTablet, + isWearable, + isXR +}; diff --git a/test/unit/device-utils.js b/test/unit/device-utils.js new file mode 100644 index 0000000..400b412 --- /dev/null +++ b/test/unit/device-utils.js @@ -0,0 +1,47 @@ +const assert = require('assert'); +const { UAParser } = require('../../src/main/ua-parser'); +const { isMobile, isSmartTV, isTablet, isWearable, isXR } = require('../../src/device-utils/ua-parser-device-utils'); + +describe('Device type check', () => { + + const advanM4 = 'Mozilla/5.0 (Linux; U; Android 6.0; ADVAN M4 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36 OPR/28.0.2254.119214'; + const galaxyWatch5 = 'Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-R925U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2. Chrome/111.0.5563.116 Mobile Safari/537.36'; + const miTV = 'Mozilla/5.0 (Linux; Android 10; MiTV-MOOQ0 Build/QTG3.200305.006; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.61 Mobile Safari/537.36'; + const nokiaT20 = 'Mozilla/5.0 (Linux; Android 11; Nokia T20 Build/RP1A.201005.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/93.0.4577.62 Safari/537.36'; + const questPro = 'Mozilla/5.0 (X11; Linux x86_64; Quest Pro) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/24.4.0.22.60.426469926 SamsungBrowser/4.0 Chrome/106.0.5249.181 VR Safari/537.36'; + + it('isMobile()', () => { + assert.strictEqual(isMobile(advanM4), true); + assert.strictEqual(isMobile(galaxyWatch5), false); + assert.strictEqual(isMobile(nokiaT20), false); + assert.strictEqual(isMobile(miTV), false); + + const uaResult = UAParser(advanM4); + const { device: uaDevice } = uaResult; + assert.strictEqual(isMobile(uaResult), true); + assert.strictEqual(isMobile(uaDevice), true); + assert.strictEqual(isMobile(isMobile), false); + }); + + it('isSmartTV()', () => { + assert.strictEqual(isSmartTV(nokiaT20), false); + assert.strictEqual(isSmartTV(galaxyWatch5), false); + assert.strictEqual(isSmartTV(miTV), true); + }); + + it('isTablet()', () => { + assert.strictEqual(isTablet(nokiaT20), true); + assert.strictEqual(isTablet(questPro), false); + }); + + it('isWearable()', () => { + assert.strictEqual(isWearable(advanM4), false); + assert.strictEqual(isWearable(galaxyWatch5), true); + assert.strictEqual(isWearable(miTV), false); + }); + + it('isXR()', () => { + assert.strictEqual(isXR(advanM4), false); + assert.strictEqual(isXR(questPro), true); + }); +});