diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac7494..2317396 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Bowser Changelog +### 2.1.0 (January 24, 2019) +- [ADD] Add new `Parser.getEngineName()` method (#288) +- [ADD] Add detection of ChromeOS (#287) +- [FIX] Fix README + ### 2.0.0 (January 19, 2019) - [ADD] Support a non strict equality in `Parser.satisfies()` (#275) - [ADD] Add Android versions names (#276) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a4640e..2652439 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,31 @@ # Contributing -The project runs Git-flow, where the `master` branch is the development one and `production` is the production one. +We're always open to pull requests or code reviews. Everyone can become a permanent contributor. Just ping @lancedikson in the issues or on Twitter ❤️ -In a nutshell, if you're about to propose a new feature with adding some totally new functionality to `bowser`, it's better to branch from `master` and make a PR pointing back to `master` as well. -If it's a small hotfix, fix a typo in the docs or you've added support for a new browser/OS/platform/etc, then it's better to branch from `production` and make a PR pointing back to `production`. -Following these simple rules will help to maintain the repo a lot! Thanks ❤️ +## Branches + +The project runs Git-flow, where the `master` branch is for development and `production` is for production. + +In a nutshell, if you are proposing a new feature that adds totally new functionality to `bowser`, it's better to branch from `master` and make a PR pointing back to `master` as well. + +If it's a small hot-fix, an improvement to the docs, or added support for a new browser/OS/platform/etc, then it's better to branch from `production` and make a PR pointing back to `production`. + +Following these simple rules will really help maintain the repo! Thanks ❤️ + +## Adding Tests + +See the list in `test/acceptance/useragentstrings.yml` with example user agents and their expected `bowser` object. + +Whenever you add support for new browsers or notice a bug / mismatch, please update the list and +check if all tests are still passing. + +## Testing + +If you'd like to contribute a change to `bowser`, modify the files in `src/`, and run the following (you'll need `node` + `npm` installed): + +``` sh +$ npm install +$ npm run build #build +$ npm test #run tests +$ npm run lint #check lint rules +``` diff --git a/README.md b/README.md index a9db3c7..4b8234d 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,23 @@ A browser detector. Because sometimes, there is no other way, and not even good The library is made to help to detect what browser your user has and gives you a convenient API to filter the users somehow depending on their browsers. -_Please, note that this is an alpha version. Check out the [1.x](https://github.com/lancedikson/bowser/tree/v1.x) branch for a stable version._ - **Changes of version 2.0** -The upcoming 2.0 version has drastically changed API. All available methods can be found in the `docs` folder from now on and on a webpage soon. + +The version 2.0 has drastically changed API. All available methods can be found in the `docs` folder from now on and on a webpage soon. + +_For legacy code, check out the [1.x](https://github.com/lancedikson/bowser/tree/v1.x) branch and install it through `npm install bowser@1.9.4`._ + # Use cases -First of all, require the library. This is a UMD Module, so it will work for AMD, Typescript and CommonJS module systems. +First of all, require the library. This is a UMD Module, so it will work for AMD, TypeScript, ES6, and CommonJS module systems. ```javascript const Bowser = require("bowser"); // CommonJS -import * as Bowser from "bowser" // Typescript +import * as Bowser from "bowser"; // TypeScript + +import Bowser from "bowser"; // ES6 (and TypeScript with --esModuleInterop enabled) ``` By default, the exported version is the *ES5 transpiled version*, which **do not** include any polyfills. @@ -41,7 +45,7 @@ You may need to use the source files, so they will be available in the package a Often we need to pick users' browser properties such as the name, the version, the rendering engine and so on. Here is an example how to do it with Bowser: ```javascript -const browser = bowser.getParser(window.navigator.userAgent); +const browser = Bowser.getParser(window.navigator.userAgent); console.log(`The current browser name is "${browser.getBrowserName()}"`); // The current browser name is "Internet Explorer" @@ -52,7 +56,7 @@ or ```javascript const impression = new Impression(); -const browser = bowser.getParser(window.navigator.userAgent); +const browser = Bowser.getParser(window.navigator.userAgent); const browserInfo = browser.getBrowser(); impression.brName = browserInfo.name; impression.brVer = browserInfo.version; @@ -61,7 +65,7 @@ impression.brVer = browserInfo.version; or ```javascript -const browser = bowser.getParser(window.navigator.userAgent); +const browser = Bowser.getParser(window.navigator.userAgent); impression.userTechData = browser.parse(); console.log(impression.userTechData); @@ -93,7 +97,7 @@ You could want to filter some particular browsers to provide any special support It could look like this: ```javascript -const browser = bowser.getParser(window.navigator.userAgent); +const browser = Bowser.getParser(window.navigator.userAgent); const isValidBrowser = browser.satisfies({ // declare browsers per OS windows: { @@ -128,25 +132,6 @@ Thus, you can define OS or platform specific rules and they will have more prior More of API and possibilities you will find in the `docs` folder. -# Contributing - -We're always open to pull requests or code reviews. Everyone can become a permanent contributor. Just ping @lancedikson in the issues or on Twitter ❤️ - -If you'd like to contribute a change to bowser, modify the files in `src/`, then run the following (you'll need node + npm installed): - -``` sh -$ npm install -$ npm run build #build -$ npm test #run tests -$ npm run lint #check lint rules -``` - -### Adding tests -See the list in `test/acceptance/useragentstrings.yml` with example user agents and their expected bowser object. - -Whenever you add support for new browsers or notice a bug / mismatch, please update the list and -check if all tests are still passing. - ### Similar Projects * [Kong](https://github.com/BigBadBleuCheese/Kong) - A C# port of Bowser. diff --git a/index.d.ts b/index.d.ts index 78108b9..49e797b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -13,7 +13,7 @@ declare namespace Bowser { * @param {boolean} skipParsing */ - function getParser(UA: string, skipParsing?: boolean): Parser.Parser; + function getParser(UA: string, skipParsing?: boolean): Parser.Parser; /** * Creates a Parser instance and runs Parser.getResult immediately @@ -26,28 +26,28 @@ declare namespace Bowser { declare namespace Parser { class Parser { - constructor(UA: string, skipParsing?: boolean); + constructor(UA: string, skipParsing?: boolean); /** * Get parsed browser object * @return {BrowserDetails} Browser's details */ - getBrowser(): BrowserDetails; + getBrowser(): BrowserDetails; /** * Get browser's name * @return {String} Browser's name or an empty string */ - getBrowserName(): string; + getBrowserName(): string; /** * Get browser's version * @return {String} version of browser */ - getBrowserVersion(): string; + getBrowserVersion(): string; /** * Get OS @@ -60,7 +60,7 @@ declare namespace Parser { * // } */ - getOS(): OSDetails; + getOS(): OSDetails; /** * Get OS name @@ -68,49 +68,49 @@ declare namespace Parser { * @return {String} name of the OS — macOS, Windows, Linux, etc. */ - getOSName(toLowerCase?: boolean): string; + getOSName(toLowerCase?: boolean): string; /** * Get OS version * @return {String} full version with dots ('10.11.12', '5.6', etc) */ - getOSVersion(): string; + getOSVersion(): string; /** * Get parsed platform * @returns {PlatformDetails} */ - getPlatform(): PlatformDetails; + getPlatform(): PlatformDetails; /** * Get platform name * @param {boolean} toLowerCase */ - getPlatformType(toLowerCase?: boolean): string; + getPlatformType(toLowerCase?: boolean): string; /** * Get parsed engine * @returns {EngineDetails} */ - getEngine(): EngineDetails; + getEngine(): EngineDetails; /** * Get parsed result * @return {ParsedResult} */ - getResult(): ParsedResult; + getResult(): ParsedResult; /** * Get UserAgent string of current Parser instance * @return {String} User-Agent String of the current object */ - getUA(): string; + getUA(): string; /** * Is anything? Check if the browser is called "anything", @@ -119,41 +119,41 @@ declare namespace Parser { * @returns {Boolean} */ - is(anything: any): boolean; + is(anything: any): boolean; /** * Parse full information about the browser */ - parse(): void; + parse(): void; /** * Get parsed browser object * @returns {BrowserDetails} */ - parseBrowser(): BrowserDetails; + parseBrowser(): BrowserDetails; /** * Get parsed engine * @returns {EngineDetails} */ - parseEngine(): EngineDetails; + parseEngine(): EngineDetails; /** * Parse OS and save it to this.parsedResult.os * @returns {OSDetails} */ - parseOS(): OSDetails; + parseOS(): OSDetails; /** * Get parsed platform * @returns {PlatformDetails} */ - parsePlatform(): PlatformDetails; + parsePlatform(): PlatformDetails; /** * Check if parsed browser matches certain conditions @@ -174,7 +174,7 @@ declare namespace Parser { * if (browser.check({desktop: { chrome: '>118.01.1322' } })) */ - satisfies(checkTree: checkTree): boolean | undefined; + satisfies(checkTree: checkTree): boolean | undefined; /** * Check if any of the given values satifies `.is(anything)` @@ -182,7 +182,7 @@ declare namespace Parser { * @returns {boolean} true if at least one condition is satisfied, false otherwise. */ - some(anythings: string[]): boolean | undefined; + some(anythings: string[]): boolean | undefined; /** * Test a UA string for a regexp @@ -191,34 +191,34 @@ declare namespace Parser { */ test(regex: RegExp): boolean; - } + } interface ParsedResult { browser: BrowserDetails; os: OSDetails; platform: PlatformDetails; engine: EngineDetails; - } + } interface Details { name?: string; version?: string; - } + } interface OSDetails extends Details { versionName?: string; - } + } interface PlatformDetails { type?: string; vendor?: string; model?: string; - } + } type BrowserDetails = Details; type EngineDetails = Details; - interface checkTree { + interface checkTree { [key: string]: any; } } diff --git a/package-lock.json b/package-lock.json index 10930d6..123cecc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "bowser", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c5be526..ec4b562 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bowser", - "version": "2.0.0", + "version": "2.1.0", "description": "Lightweight browser detector", "keywords": [ "browser", diff --git a/src/parser-os.js b/src/parser-os.js index 446a7cb..06c5c72 100644 --- a/src/parser-os.js +++ b/src/parser-os.js @@ -144,4 +144,14 @@ export default [ }; }, }, + + /* Chrome OS */ + { + test: [/CrOS/], + describe() { + return { + name: 'Chrome OS', + }; + }, + }, ]; diff --git a/src/parser.js b/src/parser.js index a296977..4893ef0 100644 --- a/src/parser.js +++ b/src/parser.js @@ -272,6 +272,19 @@ class Parser { return this.parseEngine(); } + /** + * Get engines's name + * @return {String} Engines's name or an empty string + * + * @public + */ + getEngineName(toLowerCase) { + if (toLowerCase) { + return String(this.getEngine().name).toLowerCase() || ''; + } + return this.getEngine().name || ''; + } + /** * Get parsed platform * @return {{}} @@ -437,6 +450,10 @@ class Parser { return this.getPlatformType(true) === String(platformType).toLowerCase(); } + isEngine(engineName) { + return this.getEngineName(true) === String(engineName).toLowerCase(); + } + /** * Is anything? Check if the browser is called "anything", * the OS called "anything" or the platform called "anything" diff --git a/test/acceptance/useragentstrings.yml b/test/acceptance/useragentstrings.yml index 0ee3ce4..f7a1cbe 100644 --- a/test/acceptance/useragentstrings.yml +++ b/test/acceptance/useragentstrings.yml @@ -174,7 +174,8 @@ browser: name: "Chrome" version: "29.0.1547.57" - os: {} + os: + name: "Chrome OS" platform: {} engine: name: "Blink" diff --git a/test/unit/parser.js b/test/unit/parser.js index 309aa72..17a020f 100644 --- a/test/unit/parser.js +++ b/test/unit/parser.js @@ -53,6 +53,21 @@ test('Parser.getOSVersion returns a correct result', (t) => { t.is(parser.getOSVersion(), '10.12.4'); }); +test('Parser.parseEngine is being called when getEngine() called', (t) => { + const spy = sinon.spy(parser, 'parseEngine'); + parser.getEngine(); + t.truthy(spy.called); + parser.parseEngine.restore(); +}); + +test('Parser.getEngineName gives a name of the engine', (t) => { + t.is(parser.getEngineName(), 'Blink'); +}); + +test('Parser.getEngineName gives a lower-cased name of the engine', (t) => { + t.is(parser.getEngineName(true), 'blink'); +}); + test('Skip parsing shouldn\'t parse', (t) => { t.deepEqual((new Parser(UA, true)).getResult(), {}); });