Skip to content

Commit 30de983

Browse files
committed
Alpha release of v2.0
1 parent 894512c commit 30de983

16 files changed

+279
-194
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ua-parser-js",
3-
"version": "0.7.33",
3+
"version": "2.0.0-alpha.1",
44
"authors": [
55
"Faisal Salman <[email protected]>"
66
],

changelog.md

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,42 @@
11
# UAParser.js Changelog
22

3+
# Version 2.0.0-alpha.1
4+
- Breaking changes:
5+
- Browser detection on mobile device: `Chrome => Mobile Chrome`, `Firefox => Mobile Firefox`
6+
- OS detection: `Mac OS => macOS`, `Chromium OS => Chrome OS`
7+
- Add some new methods in result object:
8+
- Add support for client hints: `withClientHints()`
9+
- Utility for easy comparison: `is()`
10+
- Utility to print full-name: `toString()`
11+
- Add support for ES module `import { UAParser } from 'ua-parser-js'`
12+
- Provide Enums `'ua-parser-js/enums'`
13+
- Provide Extensions `'ua-parser-js/extensions'`
14+
- Add new browser: Heytap, TikTok
15+
- Add new engine: LibWeb
16+
- Add new OS: SerenityOS
17+
- Improve browser detection: Yandex
18+
- Improve device detection: iPhone, Amazon Echo
19+
- Improve OS detection: iOS
20+
321
# Version 0.7 / 1.0
422

523
Version 1.0.x is basically the equivalent of version 0.7.x. See [#536](https://github.com/faisalman/ua-parser-js/issues/536) for the reason behind this confusion.
624

7-
## Version 0.7.30 / 1.0.1
25+
## Version 0.7.34 / 1.0.34
26+
- Fix Sharp Mobile detected as Huawei Tablet
27+
- Fix IE8 bug
28+
- Add new devices : Kobo e-Reader, Apple Watch, and some new SmartTV devices
29+
- Add new OS : watchOS
30+
- Improve browser detection : Kakao, Naver, Brave
31+
- Improve device detection : Oculus, iPad
32+
- Improve OS detection : Chrome OS
33+
- Using navigator.userAgentData as fallback for device.type & os.name
834

9-
- Add new browser : Obigo, UP.Browser, Klar
10-
- Add new device : Oculus, Roku
11-
- Add new OS: Maemo, HP-UX, Android-x86, Deepin, elementary OS, GhostBSD, Linspire, Manjaro, Sabayon
12-
- Improve detection for Sony Xperia 1ii, LG Android TV, and some more devices
13-
- Improve detection for ARM64 CPU
14-
- Improve detection for Windows Mobile, Netscape, Mac on PowerPC
15-
- Categorize PDA as mobile
16-
- Fix Sharp devices misjudged as Huawei
17-
- Fix trailing comma for ES3 compatibility
18-
- Some code refactor
19-
20-
## Version 0.7.31 / 1.0.2
35+
## Version 0.7.33 / 1.0.33
2136

22-
- Fix OPPO Reno A5 incorrect detection
23-
- Fix TypeError Bug
24-
- Use AST to extract regexes and verify them with safe-regex
37+
- Add new browser : Cobalt
38+
- Identify Macintosh as an Apple device
39+
- Fix ReDoS vulnerability
2540

2641
## Version 0.7.32 / 1.0.32
2742

@@ -38,11 +53,24 @@ Version 1.0.x is basically the equivalent of version 0.7.x. See [#536](https://g
3853
- Fix included commas in Safari / Mobile Safari version
3954
- Increase UA_MAX_LENGTH to 350
4055

41-
## Version 0.7.33 / 1.0.33
56+
## Version 0.7.31 / 1.0.2
4257

43-
- Add new browser : Cobalt
44-
- Identify Macintosh as an Apple device
45-
- Fix ReDoS vulnerability
58+
- Fix OPPO Reno A5 incorrect detection
59+
- Fix TypeError Bug
60+
- Use AST to extract regexes and verify them with safe-regex
61+
62+
## Version 0.7.30 / 1.0.1
63+
64+
- Add new browser : Obigo, UP.Browser, Klar
65+
- Add new device : Oculus, Roku
66+
- Add new OS: Maemo, HP-UX, Android-x86, Deepin, elementary OS, GhostBSD, Linspire, Manjaro, Sabayon
67+
- Improve detection for Sony Xperia 1ii, LG Android TV, and some more devices
68+
- Improve detection for ARM64 CPU
69+
- Improve detection for Windows Mobile, Netscape, Mac on PowerPC
70+
- Categorize PDA as mobile
71+
- Fix Sharp devices misjudged as Huawei
72+
- Fix trailing comma for ES3 compatibility
73+
- Some code refactor
4674

4775
# Version 0.8
4876

dist/ua-parser.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ua-parser.pack.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package.describe({
22
name: 'faisalman:ua-parser-js',
3-
version: '0.7.33',
3+
version: '2.0.0-alpha.1',
44
summary: 'Lightweight JavaScript-based user-agent string parser',
55
git: 'https://github.com/faisalman/ua-parser-js.git',
66
documentation: 'readme.md'

package.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "UAParser.js",
33
"name": "ua-parser-js",
4-
"version": "0.7.33",
4+
"version": "2.0.0-alpha.1",
55
"author": "Faisal Salman <[email protected]> (http://faisalman.com)",
66
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Supports browser & node.js environment",
77
"keywords": [
@@ -139,30 +139,30 @@
139139
"yuanyang <[email protected]>",
140140
"Yun Young-jin <[email protected]>",
141141
"Zach Bjornson <[email protected]>"
142-
],
142+
],
143143
"type": "commonjs",
144144
"main": "src/ua-parser.js",
145145
"module": "src/ua-parser.mjs",
146146
"exports": {
147-
"." : {
147+
".": {
148148
"require": "./src/ua-parser.js",
149149
"import": "./src/ua-parser.mjs"
150150
},
151-
"./enums" : {
152-
"require": "./src/ua-parser-enum.js",
153-
"import": "./src/ua-parser-enum.mjs"
151+
"./enums": {
152+
"require": "./src/enum/ua-parser-enum.js",
153+
"import": "./src/enum/ua-parser-enum.mjs"
154154
},
155-
"./extensions" : {
156-
"require": "./src/ua-parser-extension.js",
157-
"import": "./src/ua-parser-extension.mjs"
155+
"./extensions": {
156+
"require": "./src/extension/ua-parser-extension.js",
157+
"import": "./src/extension/ua-parser-extension.mjs"
158158
}
159159
},
160160
"files": [
161161
"dist",
162162
"src"
163163
],
164164
"scripts": {
165-
"build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle && uglifyjs src/ua-parser-enum.js -o dist/ua-parser-enum.min.js --comments '/^ Enum/' && node -e \"const fs=require('fs');fs.writeFileSync('src/ua-parser.mjs','// Generated ESM version of UAParser.js\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser.js\\n\\nconst window = undefined;\\n\\n'+fs.readFileSync('src/ua-parser.js','utf-8').replace(/\\(func[\\s\\S]+strict\\';/ig,'').replace(/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'),'utf-8');fs.writeFileSync('src/ua-parser-enum.mjs','// Generated ESM version of UAParser.js enums\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser-enum.js\\n\\n'+fs.readFileSync('src/ua-parser-enum.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8');fs.writeFileSync('src/ua-parser-extension.mjs','// Generated ESM version of UAParser.js extensions\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser-extension.js\\n\\n'+fs.readFileSync('src/ua-parser-extension.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8')\"",
165+
"build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle && node -e \"const fs=require('fs');fs.writeFileSync('src/ua-parser.mjs','// Generated ESM version of UAParser.js\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser.js\\n\\nconst window = undefined;\\n\\n'+fs.readFileSync('src/ua-parser.js','utf-8').replace(/\\(func[\\s\\S]+strict\\';/ig,'').replace(/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'),'utf-8');fs.writeFileSync('src/enum/ua-parser-enum.mjs','// Generated ESM version of UAParser.js enums\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/enum/ua-parser-enum.js\\n\\n'+fs.readFileSync('src/enum/ua-parser-enum.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8');fs.writeFileSync('src/extension/ua-parser-extension.mjs','// Generated ESM version of UAParser.js extensions\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/extension/ua-parser-extension.js\\n\\n'+fs.readFileSync('src/extension/ua-parser-extension.js','utf-8').replace(/const UA.+\\)/ig,'import UAParser from \\'ua-parser-js\\'').replace(/module\\.exports =/ig,'export'),'utf-8')\"",
166166
"test": "jshint src/ua-parser.js && mocha -R nyan test",
167167
"test-ci": "jshint src/ua-parser.js && mocha -R spec test",
168168
"verup": "node ./node_modules/verup",

readme.md

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,19 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro
4343

4444
---
4545

46+
# Version 2.0
47+
What's new & breaking, please read [CHANGELOG](changelog.md) before upgrading.
48+
4649
# Documentation
47-
### UAParser([user-agent:string][,extensions:object][,headers:object(since@1.1)])
50+
### UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])
4851

4952
In the browser environment you dont need to pass the user-agent string to the function, you can just call the funtion and it should automatically get the string from the `window.navigator.userAgent`, but that is not the case in nodejs. The user-agent string must be passed in' nodejs for the function to work. Usually you can find the user agent in: `request.headers["user-agent"]`.
5053

5154

5255
## Constructor
5356
When you call `UAParser` with the `new` keyword, `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string.
5457
Like so:
55-
* `new UAParser([user-agent:string][,extensions:object][,headers:object(since@1.1)])`
58+
* `new UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])`
5659
```js
5760
let parser = new UAParser("your user-agent here"); // you need to pass the user-agent for nodejs
5861
console.log(parser); // {}
@@ -65,22 +68,19 @@ console.log(parserResults);
6568
"os" : {},
6669
"device" : {},
6770
"cpu" : {}
68-
69-
70-
,"ua_ch" : {}
7171
} */
7272
```
7373

7474
When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
75-
* `UAParser([user-agent:string][,extensions:object][,headers:object(since@1.1)])`
76-
* returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} /* added [email protected]: ua_ch: {} */ }`
75+
* `UAParser([user-agent:string][,extensions:object][,headers:object(since@2.0)])`
76+
* returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
7777

7878
## Methods
7979

8080
#### Methods table
8181
The methods are self explanatory, here's a small overview on all the available methods:
8282
* `getResult()` - returns all function object calls, user-agent string, browser info, cpu, device, engine, os:
83-
`{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} /* added [email protected]: ua_ch: {} */ }`.
83+
`{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`.
8484

8585
* `getBrowser()` - returns the browser name and version.
8686
* `getDevice()` - returns the device model, type, vendor.
@@ -93,7 +93,7 @@ The methods are self explanatory, here's a small overview on all the available m
9393
---
9494

9595
* `getResult()`
96-
* returns `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} /* added [email protected]: ua_ch: {} */ }`
96+
* returns `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
9797

9898
* `getBrowser()`
9999
* returns `{ name: '', version: '' }`
@@ -113,7 +113,7 @@ NetSurf, Netfront, Netscape, NokiaBrowser, Obigo, Oculus Browser, OmniWeb,
113113
Opera Coast, Opera [Mini/Mobi/Tablet], PaleMoon, PhantomJS, Phoenix, Polaris,
114114
Puffin, QQ, QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, [Mobile] Safari,
115115
Sailfish Browser, Samsung Browser, SeaMonkey, Silk, Skyfire, Sleipnir, Slim,
116-
SlimBrowser, Swiftfox, Tesla, Tizen Browser, UCBrowser, UP.Browser, Viera,
116+
SlimBrowser, Swiftfox, Tesla, TikTok, Tizen Browser, UCBrowser, UP.Browser, Viera,
117117
Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m, Whale Browser, ...
118118

119119
# 'browser.version' determined dynamically
@@ -148,8 +148,8 @@ Siemens, Sony[Ericsson], Sprint, Tesla, Vivo, Vodafone, Xbox, Xiaomi, Zebra, ZTE
148148

149149
```sh
150150
# Possible 'engine.name'
151-
Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, Links, Lynx, NetFront,
152-
NetSurf, Presto, Tasman, Trident, w3m, WebKit
151+
Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, LibWeb, Links, Lynx,
152+
NetFront, NetSurf, Presto, Tasman, Trident, w3m, WebKit
153153

154154
# 'engine.version' determined dynamically
155155
```
@@ -165,8 +165,9 @@ Fuchsia, Gentoo, GhostBSD, GNU, Haiku, HarmonyOS, HP-UX, Hurd, iOS, Joli, KaiOS,
165165
Linpus, Linspire,Linux, Mac OS, Maemo, Mageia, Mandriva, Manjaro, MeeGo, Minix,
166166
Mint, Morph OS, NetBSD, NetRange, NetTV, Nintendo, OpenBSD, OpenVMS, OS/2, Palm,
167167
PC-BSD, PCLinuxOS, Plan9, PlayStation, QNX, Raspbian, RedHat, RIM Tablet OS,
168-
RISC OS, Sabayon, Sailfish, Series40, Slackware, Solaris, SUSE, Symbian, Tizen,
169-
Ubuntu, Unix, VectorLinux, Viera, watchOS, WebOS, Windows [Phone/Mobile], Zenwalk, ...
168+
RISC OS, Sabayon, Sailfish, SerenityOS, Series40, Slackware, Solaris, SUSE, Symbian,
169+
Tizen, Ubuntu, Unix, VectorLinux, Viera, watchOS, WebOS, Windows [Phone/Mobile],
170+
Zenwalk, ...
170171

171172
# 'os.version' determined dynamically
172173
```
@@ -186,10 +187,10 @@ Ubuntu, Unix, VectorLinux, Viera, watchOS, WebOS, Windows [Phone/Mobile], Zenwal
186187
* set UA string to be parsed
187188
* returns current instance
188189

189-
#### * `is():boolean` utility `since@1.1`
190+
#### * `is():boolean` utility `since@2.0`
190191

191192
```js
192-
// Is just a shorthand to check whether specified item has a property with equals value (case-insensitive)
193+
// Is just a shorthand comparison to check whether the value of specified item equals one of its properties (in a case-insensitive way)
193194
// so that instead of write it using `==` operator like this:
194195

195196
let ua = UAParser();
@@ -202,15 +203,10 @@ if (device.type == "smarttv" || device.vendor == "Samsung") {}
202203
// we can also write the comparison above into as follow:
203204

204205
if (device.is("mobile") && !os.is("iOS")) {}
205-
if (device.is("smarttv") || device.is("Samsung")) {}
206+
if (device.is("SmartTV") || device.is("SaMsUnG")) {}
206207

207208
/*
208-
Each properties will be checked in this particular order:
209-
* browser : name
210-
* cpu : architecture
211-
* device : type, model, vendor
212-
* engine : name
213-
* os : name
209+
For device, properties will be checked in this particular order: type, model, vendor
214210
*/
215211

216212
// Another examples:
@@ -250,7 +246,7 @@ let engine = uap.getEngine();
250246
engine.is("Blink"); // true
251247
```
252248

253-
#### * `toString():string` utility `since@1.1`
249+
#### * `toString():string` utility `since@2.0`
254250

255251
```js
256252
// Retrieve full-name values as a string
@@ -291,11 +287,12 @@ engine.version; // "28.0.1500.95"
291287
engine.toString(); // "Blink 28.0.1500.95"
292288
```
293289

294-
#### * `withClientHints():Promise<object>|Thenable<object>` `since@1.1`
290+
#### * `withClientHints():Promise<object>|Thenable<object>` `since@2.0`
295291

296-
Unlike reading user-agent data, accessing client-hints data in browser-environment must be done in an asynchronous way. Worry not, you can chain the UAParser's `get*` method with `withClientHints()` to read the client-hints data as well that will return the updated data as a `Promise`. In nodejs-environment / browser-environment with non-secure context or without client-hints support (basically anything that's not chromium-based) this will return the updated data as a `Thenable` (can be chained with `then()`).
292+
Recently Chrome limits the information exposed through user-agent and introduces a new experimental set of data called "client-hints". In browser-environment, obtaining the client-hints data via JavaScript must be done in an asynchronous way. In `UAParser` you can chain the result object from `get*` method with `withClientHints()` to also read the client-hints data from the browser and return the updated data as a `Promise`.
297293

298294
```js
295+
// client-side example
299296
(async function () {
300297
let ua = new UAParser();
301298

@@ -314,12 +311,43 @@ Unlike reading user-agent data, accessing client-hints data in browser-environme
314311
})();
315312
```
316313

314+
Along with `User-Agent` HTTP header, Chrome also sends this client-hints data by default under `Sec-CH-UA-*` HTTP headers in each request. In server-side development, you can capture this extra information by passing the `req.headers` to `UAParser()` (see examples below). When using `withClientHints()` in nodejs environment and browser without client-hints support (basically anything that's not Chromium-based) the updated data will be returned as a `Thenable` (has `then()` method).
315+
316+
```js
317+
// server-side example
318+
319+
// Suppose we got a request having these HTTP headers:
320+
const request = {
321+
headers : {
322+
'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
323+
324+
'sec-ch-ua-mobile' : '?1',
325+
'sec-ch-ua-model' : 'Galaxy S3 Marketing',
326+
'sec-ch-ua-platform' : 'Android'
327+
}
328+
};
329+
330+
const result1 = UAParser(request.headers); // parse only "user-agent" header
331+
const result2 = UAParser(request.headers).withClientHints(); // update with "sec-ch-ua" headers
332+
333+
console.log(result1.os.name); // "Linux"
334+
console.log(result1.device.type); // undefined
335+
console.log(result1.device.model); // undefined
336+
337+
console.log(result2.os.name); // "Android"
338+
console.log(result2.device.type); // "mobile"
339+
console.log(result2.device.model); // "Galaxy S3 Marketing"
340+
341+
new UAParser(request.headers).getBrowser().withClientHints().then((browser) => {
342+
console.log(browser.toString()); // Chrome 110.0.0.0
343+
});
344+
```
317345

318346
## Extending Regex
319347

320348
If you want to detect something that's not currently provided by UAParser.js (eg: `bots`, specific apps, etc), you can pass a list of regexes to extend internal UAParser.js regexes with your own.
321349

322-
* `UAParser([uastring,] extensions [,headers:object(since@1.1)])`
350+
* `UAParser([uastring,] extensions [,headers:object(since@2.0)])`
323351

324352
```js
325353
// Example:
@@ -389,18 +417,6 @@ console.log(myParser2.setUA(myUA2).getDevice()); // {vendor: "MyTab", model: "1
389417
cpu: {
390418
architecture: ""
391419
}
392-
393-
394-
,ua_ch: {
395-
architecture: "",
396-
brands: "",
397-
bitness: "",
398-
fullVersionList: "",
399-
mobile: "",
400-
model: "",
401-
platform: "",
402-
platformVersion: ""
403-
}
404420
}
405421
*/
406422
// Default result depends on current window.navigator.userAgent value
@@ -453,7 +469,7 @@ http.createServer(function (req, res) {
453469
// get user-agent header
454470
var ua = uap(req.headers['user-agent']);
455471

456-
/* // BEGIN since@1.1 - you can also pass client-hints data to UAParser
472+
/* // BEGIN since@2.0 - you can also pass client-hints data to UAParser
457473
458474
// note: only works in secure context (https:// or localhost or file://)
459475
@@ -463,7 +479,7 @@ http.createServer(function (req, res) {
463479
464480
var ua = uap(req.headers);
465481
466-
// END since@1.1 */
482+
// END since@2.0 */
467483

468484
// write the result as response
469485
res.end(JSON.stringify(ua, null, ' '));
@@ -477,14 +493,13 @@ console.log('Server running at http://127.0.0.1:1337/');
477493

478494
```js
479495
import { UAParser } from 'ua-parser-js';
480-
import { CPUArch, DeviceType } from 'ua-parser-js/enums';
481496

482-
const { cpu, device } = UAParser('Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2a1pre) Gecko/20090928 Firefox/3.5 Maemo Browser 1.4.1.22 RX-51 N900');
497+
const { browser, cpu, device } = UAParser('Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2a1pre) Gecko/20090928 Firefox/3.5 Maemo Browser 1.4.1.22 RX-51 N900');
483498

484-
console.log(browser.name) // Maemo Browser
485-
console.log(cpu.is(CPUArch.ARM)) // true
486-
console.log(device.is(DeviceType.MOBILE)) // true
487-
console.log(device.model) // N900
499+
console.log(browser.name); // Maemo Browser
500+
console.log(cpu.is('arm')); // true
501+
console.log(device.is('mobile')); // true
502+
console.log(device.model); // N900
488503
```
489504

490505
## Using TypeScript

0 commit comments

Comments
 (0)