1
0
mirror of https://github.com/lancedikson/bowser synced 2025-06-13 13:03:52 +00:00

Compare commits

...

549 Commits

Author SHA1 Message Date
Denis Demchenko
8c489bd98b
chore: move the token to secrets 2024-08-12 13:42:09 +03:00
Meir Roth
5bab4ee97d
docs: remove non-existing links in README 2024-04-28 23:42:58 +03:00
Naor Peled
16c9f22546
ci: attempt to resolve merge to master errors (#546) 2024-04-20 14:54:03 +03:00
Naor Peled
327e6f5e51
ci: add release drafter (#545) 2024-04-20 14:35:56 +03:00
pastak
0626bf8c8c
Fix link to doc page on README.md (#543) 2023-12-11 10:37:33 +02:00
Naor Peled
94ab87ec0e
feat(constants): add bot as a platform (#540) (#541)
Co-authored-by: Lucio Martinez <martinezlucio.com@gmail.com>
2023-11-27 16:21:18 +02:00
Amelie
07462efb6a
feat: update types of parser methods (#449) 2023-11-17 21:01:45 +02:00
idmadj
f8fcea59e7
docs: fix getBrowserTypeByAlias docs (#467) 2023-11-17 20:55:43 +02:00
daniol
4481f5aab3
feat: add Nokia Vendor (#448) 2023-11-17 20:54:44 +02:00
James Cleveland
0c7380dbf9
fix: use default export in type definitions (#465) 2023-11-17 20:49:07 +02:00
Mehmet Akif Yücel
bb8f94efcd
feat: add Pale Moon browser support (#495) 2023-11-17 20:47:16 +02:00
Matheus Hahn
29222b2fcf
docs: update Typescript definition file (#500) 2023-11-17 20:46:29 +02:00
Naor Peled
69bc6c2dbf
revert(workflows): rollback to Node 12.16.3 (#537) 2023-11-17 20:45:54 +02:00
Naor Peled
9c1588a43e
chore: add CodeQL config 2023-11-13 11:56:25 +02:00
Naor Peled
fefa53ad95
fix(docs): resolve typos (#528) 2023-11-13 11:11:43 +02:00
Naor Peled
efb8e612a5
ci: move to Github Actions (#530) 2023-11-13 11:11:28 +02:00
Connor Bär
b86bce16af
fix(parser): resolve issues with array detection (#516)
- this change resolves issues with Next.js middlewares
2023-11-13 11:10:39 +02:00
Denis Demchenko
f09411489c Merge tag '2.11.0'
2.11.0 2.11.0
2020-09-12 11:22:47 +03:00
Denis Demchenko
e188e8aa73 Merge branch '2.11.0' into production 2020-09-12 11:22:47 +03:00
Denis Demchenko
1d64ecab12 chore: bump version, write changelog and docs 2020-09-12 11:22:31 +03:00
Ricard Fredin
5b11ac25ca Add missing typescript property declaration
The method getEngineName exists both in the project and the official docs. It's just missing in the typescript declaration file.
2020-09-12 10:39:01 +03:00
Denis Demchenko
53d54e248c
Merge pull request #428 from lancedikson/dependabot/npm_and_yarn/lodash-4.17.19
chore(deps): bump lodash from 4.17.15 to 4.17.19
2020-09-12 10:37:53 +03:00
Denis Demchenko
b7c67e9094
Merge pull request #431 from lancedikson/dependabot/npm_and_yarn/elliptic-6.5.3
chore(deps): bump elliptic from 6.5.1 to 6.5.3
2020-09-12 10:37:25 +03:00
Denis Demchenko
b2383edfcd
Merge pull request #440 from lancedikson/dependabot/npm_and_yarn/yargs-parser-13.1.2
chore(deps): bump yargs-parser from 13.1.1 to 13.1.2
2020-09-12 10:36:55 +03:00
Denis Demchenko
e431acf578
Merge pull request #442 from lancedikson/dependabot/npm_and_yarn/http-proxy-1.18.1
chore(deps): bump http-proxy from 1.18.0 to 1.18.1
2020-09-12 10:36:39 +03:00
Denis Demchenko
c504b110bb
Merge pull request #427 from YongliangDing/declaration-update
Update @returns of Parser.prototype.parse
2020-09-12 10:35:50 +03:00
Denis Demchenko
a6317d24ca
Merge pull request #438 from Cordazar/patch-2
Add missing typescript property declaration
2020-09-12 10:27:13 +03:00
Denis Demchenko
24dab5f699
Merge pull request #437 from willamesoares/include-alias-check
feat: add support for using alias in 'is' method
2020-09-12 10:25:35 +03:00
Denis Demchenko
444c54a726
Merge pull request #436 from willamesoares/master
feat(browser): add detection for Miui Browser
2020-09-12 10:25:04 +03:00
dependabot[bot]
bf24d05d5e
chore(deps): bump http-proxy from 1.18.0 to 1.18.1
Bumps [http-proxy](https://github.com/http-party/node-http-proxy) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/http-party/node-http-proxy/releases)
- [Changelog](https://github.com/http-party/node-http-proxy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/http-party/node-http-proxy/compare/1.18.0...1.18.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-10 04:58:23 +00:00
dependabot[bot]
1e4c408452
chore(deps): bump yargs-parser from 13.1.1 to 13.1.2
Bumps [yargs-parser](https://github.com/yargs/yargs-parser) from 13.1.1 to 13.1.2.
- [Release notes](https://github.com/yargs/yargs-parser/releases)
- [Changelog](https://github.com/yargs/yargs-parser/blob/master/docs/CHANGELOG-full.md)
- [Commits](https://github.com/yargs/yargs-parser/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-04 23:31:17 +00:00
Ricard Fredin
0deba6685e
Add missing typescript property declaration
The method getEngineName exists both in the project and the official docs. It's just missing in the typescript declaration file.
2020-08-28 22:02:26 +02:00
Will Soares
a9c4677c86 feat: add support for using alias in 'is' method 2020-08-23 16:55:29 -03:00
Will Soares
53d18c8994 increase test coverage 2020-08-23 14:42:33 -03:00
Will Soares
d5fe5657d1 feat(browser): add detection for Miui Browser 2020-08-23 13:58:07 -03:00
dependabot[bot]
c925fd755b
chore(deps): bump elliptic from 6.5.1 to 6.5.3
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.1 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.1...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-31 08:51:34 +00:00
dependabot[bot]
867992471a
chore(deps): bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-17 18:51:57 +00:00
dingyongliang
1bde6c6c7e Update @returns of Parser.prototype.parse 2020-07-14 15:04:07 +08:00
Denis Demchenko
33d6f9a37d Merge branch '2.10.0' into production 2020-07-09 22:12:50 +03:00
Denis Demchenko
d1a6532d82 Merge tag '2.10.0'
2.10.0 2.10.0
2020-07-09 22:12:50 +03:00
Denis Demchenko
cc546cfb44 chore(docs): regen docs 2020-07-09 22:11:59 +03:00
Denis Demchenko
77f394c8e7 chore(package): bump version, write changelog 2020-07-09 22:08:32 +03:00
Denis Demchenko
7adb0017dd
Merge pull request #397 from lancedikson/greenkeeper/sinon-9.0.0
Update sinon to the latest version 🚀
2020-07-09 21:51:01 +03:00
Denis Demchenko
a7bc7110e2
Merge pull request #417 from lancedikson/greenkeeper/compression-webpack-plugin-4.0.0
Update compression-webpack-plugin to the latest version 🚀
2020-07-09 21:50:45 +03:00
Denis Demchenko
7a273350d9
Merge pull request #410 from lancedikson/dependabot/npm_and_yarn/acorn-6.4.1
chore(deps): bump acorn from 6.2.0 to 6.4.1
2020-07-09 21:39:28 +03:00
Denis Demchenko
3d167b278e
Merge pull request #421 from lancedikson/greenkeeper/gh-pages-3.0.0
Update gh-pages to the latest version 🚀
2020-07-09 21:38:54 +03:00
Denis Demchenko
41c30ec722 fix(chore): bug with babel/helper-compilation on build
No "exports" main resolved in /home/runner/work/bowser/bowser/node_modules/@babel/helper-compilation-targets/package.json
2020-07-09 21:27:15 +03:00
Denis Demchenko
ba8f7d8a54 chore(tests): fix tests 2020-07-09 21:23:20 +03:00
Denis Demchenko
725de76e14 Revert "chore(tests): fix tests for Firefox iOS"
This reverts commit 9edfabf9
2020-07-09 21:23:10 +03:00
Denis Demchenko
9edfabf98a chore(tests): fix tests for Firefox iOS
relevant to #401
2020-06-02 00:32:35 +03:00
Denis Demchenko
3813d92a55 feat(browser): add detection of Opera Touch
fixes #414
2020-06-02 00:16:43 +03:00
Denis Demchenko
dbb433945a chore(travis): fix node_js version 2020-06-01 23:44:54 +03:00
Denis Demchenko
d3d710d158
Add bowser-online to README.md
closes #419
2020-06-01 23:39:46 +03:00
Denis Demchenko
9007a9e393
Merge pull request #415 from acailly/feat/handle-firefox-ipad-ios13
handle Firefox on iPad on iOS 13
2020-06-01 23:34:43 +03:00
Denis Demchenko
8fe4b98a56
Merge pull request #409 from pastak/master
add toLowerCase option to getBrowserName in typing
2020-06-01 23:33:00 +03:00
greenkeeper[bot]
57e6d2b5d3
chore(package): update lockfile package-lock.json 2020-05-29 20:31:29 +00:00
greenkeeper[bot]
98f32dfbf5
chore(package): update gh-pages to version 3.0.0 2020-05-29 20:31:26 +00:00
greenkeeper[bot]
a61817abb1
chore(package): update lockfile package-lock.json 2020-05-12 13:33:50 +00:00
greenkeeper[bot]
538ee8fe0e
chore(package): update compression-webpack-plugin to version 4.0.0 2020-05-12 13:33:47 +00:00
acailly
cb242c0242 handle Firefox on iPad on iOS 13 2020-04-28 11:37:01 +02:00
dependabot[bot]
a7cff0b965
chore(deps): bump acorn from 6.2.0 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.2.0 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.2.0...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-04-04 19:08:06 +00:00
pastak
efa7801204
add toLowerCase option to getBrowserName in typing
ref: a990b6b2f6/src/parser.js (L124)
2020-03-31 18:20:15 +09:00
Denis Demchenko
a990b6b2f6
Merge pull request #398 from pkuczynski/patch-1
Exclude unnecessary files from the npm package
2020-03-01 13:26:36 +02:00
Piotr Kuczynski
13ab38aebd
Exclude unnecessary files from the npm package
Listed a few files and folders which are currently included in the published npm package, while they should not be.
2020-02-25 16:58:43 +01:00
greenkeeper[bot]
437b6536ca
chore(package): update lockfile package-lock.json 2020-02-19 11:44:47 +00:00
greenkeeper[bot]
c83b241238
chore(package): update sinon to version 9.0.0 2020-02-19 11:44:43 +00:00
Denis Demchenko
743050f42e Merge branch '2.9.0' into production 2020-01-28 22:26:23 +02:00
Denis Demchenko
a1cbad9455 Merge tag '2.9.0'
2.9.0 2.9.0
2020-01-28 22:26:23 +02:00
Denis Demchenko
6add52d49c chore(package): bump version, write changelog 2020-01-28 22:26:13 +02:00
Denis Demchenko
0a790b84b8
Merge pull request #394 from lancedikson/greenkeeper/monorepo.babel7-20200114033043
Greenkeeper/monorepo.babel7 20200114033043
2020-01-28 21:55:41 +02:00
Denis Demchenko
433955ac68
Merge branch 'master' into greenkeeper/monorepo.babel7-20200114033043 2020-01-28 21:53:59 +02:00
Denis Demchenko
9af50fd1c7
Merge pull request #393 from lancedikson/greenkeeper/ava-3.0.0
Update ava to the latest version 🚀
2020-01-28 21:52:16 +02:00
Denis Demchenko
214cdb52bc
Merge pull request #392 from lancedikson/greenkeeper/eslint-plugin-ava-10.0.0
Update eslint-plugin-ava to the latest version 🚀
2020-01-28 21:52:02 +02:00
Denis Demchenko
07fcffe812
Merge pull request #390 from ashernguyen/AddTypeForIsBrowser
added type definition for `isBrowser` in Parser Class
2020-01-28 21:51:34 +02:00
Denis Demchenko
a8aa331c39
Merge pull request #388 from DarkPurple141/types-update
fix: only include types
2020-01-28 21:50:28 +02:00
greenkeeper[bot]
a4a1a86d25
chore(package): update lockfile package-lock.json 2020-01-19 15:21:11 +00:00
greenkeeper[bot]
be8860b731
chore(package): update ava to version 3.0.0 2020-01-19 15:21:06 +00:00
greenkeeper[bot]
5131706495
chore(package): update lockfile package-lock.json 2020-01-19 15:14:42 +00:00
greenkeeper[bot]
db8e9d4417
chore(package): update eslint-plugin-ava to version 10.0.0 2020-01-19 15:14:38 +00:00
greenkeeper[bot]
341dd8ef40
chore(package): update lockfile package-lock.json 2020-01-15 17:07:05 +00:00
greenkeeper[bot]
2132446318
chore(package): update @babel/register to version 7.8.3 2020-01-15 17:07:01 +00:00
greenkeeper[bot]
50f5a73386
chore(package): update @babel/preset-env to version 7.8.2 2020-01-15 17:06:57 +00:00
greenkeeper[bot]
e575388f48
chore(package): update @babel/polyfill to version 7.8.3 2020-01-15 17:06:54 +00:00
greenkeeper[bot]
b0b505fbe2
chore(package): update @babel/core to version 7.8.0 2020-01-15 17:06:49 +00:00
greenkeeper[bot]
48866a119e
chore(package): update @babel/cli to version 7.8.3 2020-01-15 17:06:46 +00:00
Asher Nguyen
a523ded89c added type definition for parser.isBrowser 2020-01-13 15:18:02 +11:00
Alex Hinds
7ebcbd799b include types 2020-01-06 15:54:39 +11:00
Alex Hinds
4e492fb6ae Merge branch 'master' of github.com:lancedikson/bowser into types-update 2020-01-06 15:52:21 +11:00
Alex Hinds
3544195aeb remove re-export 2020-01-06 15:52:14 +11:00
Denis Demchenko
f32c4fdc97 Merge branch '2.8.1' into production 2019-12-26 23:28:18 +02:00
Denis Demchenko
bdc8355216 Merge tag '2.8.1'
2.8.1 2.8.1
2019-12-26 23:28:18 +02:00
Denis Demchenko
01f5f2281e chore(package): bump version, write changelog 2019-12-26 23:28:09 +02:00
Denis Demchenko
24d1ce5e2c Revert "Merge pull request #382 from DarkPurple141/types-update"
This reverts commit 406e39d2fe, reversing
changes made to d238da4906.
2019-12-26 23:26:36 +02:00
Denis Demchenko
8e078bb0f4 Merge tag '2.8.0'
2.8.0 2.8.0
2019-12-26 16:46:14 +02:00
Denis Demchenko
16843fd15f Merge branch '2.8.0' into production 2019-12-26 16:46:13 +02:00
Denis Demchenko
ca7357338f chore(package): bump version 2019-12-26 16:45:29 +02:00
Denis Demchenko
50a4644a4e chore(changelog): write changelog 2019-12-26 16:43:56 +02:00
Denis Demchenko
6b59afee62
Merge pull request #386 from lancedikson/greenkeeper/nyc-15.0.0
Update nyc to the latest version 🚀
2019-12-26 16:21:01 +02:00
Denis Demchenko
15442b789b
Merge branch 'master' into greenkeeper/nyc-15.0.0 2019-12-26 16:18:07 +02:00
Denis Demchenko
a62e610f36
Merge pull request #385 from lancedikson/greenkeeper/babel-plugin-istanbul-6.0.0
Update babel-plugin-istanbul to the latest version 🚀
2019-12-26 16:16:41 +02:00
Denis Demchenko
bc3983cb8f
Merge pull request #384 from lancedikson/greenkeeper/sinon-8.0.0
Update sinon to the latest version 🚀
2019-12-26 16:16:16 +02:00
Denis Demchenko
3abf60fd8f
Merge pull request #361 from opencollective/opencollective
Activating Open Collective
2019-12-26 15:57:22 +02:00
Denis Demchenko
406e39d2fe
Merge pull request #382 from DarkPurple141/types-update
fix: update types to include constants in types.d.ts
2019-12-26 15:56:37 +02:00
Denis Demchenko
d238da4906
Merge pull request #383 from oliverfoster/issue/359
fixes #359 IE11 Added Array.prototype.find and Object.assign polyfills
2019-12-26 15:55:29 +02:00
Denis Demchenko
366a9c47e9
Merge pull request #381 from Tindtily/feature/add-wechat-ua
add windowswechat ua
2019-12-26 15:50:21 +02:00
Denis Demchenko
de5b4e02fe
Merge pull request #379 from neckro/production
Correctly detect Firefox on iPad
2019-12-26 15:48:46 +02:00
Denis Demchenko
9ecf3e94c3
Merge pull request #375 from Farfurix/add-electron
Add Electron support
2019-12-26 15:46:23 +02:00
greenkeeper[bot]
164835e190
chore(package): update lockfile package-lock.json 2019-12-23 01:13:49 +00:00
greenkeeper[bot]
0353113434
chore(package): update nyc to version 15.0.0 2019-12-23 01:13:44 +00:00
greenkeeper[bot]
4481d39247
chore(package): update lockfile package-lock.json 2019-12-23 01:00:00 +00:00
greenkeeper[bot]
460858d826
chore(package): update babel-plugin-istanbul to version 6.0.0 2019-12-23 00:59:55 +00:00
greenkeeper[bot]
0f57f77cbf
chore(package): update lockfile package-lock.json 2019-12-22 16:29:20 +00:00
greenkeeper[bot]
8122ad99a0
chore(package): update sinon to version 8.0.0 2019-12-22 16:29:15 +00:00
Alex Hinds
8fbbc33d87 Amended re-export to also import 2019-12-20 08:50:05 +11:00
Oliver foster
5a6af193d2 Extended test cases and fixed bug 2019-12-19 12:00:46 +00:00
Oliver foster
f27c7e0580 Edited typo 2019-12-19 11:49:50 +00:00
Oliver foster
b74bb0caa2 Added polyfill tests 2019-12-19 11:46:15 +00:00
Oliver foster
cad365b53e Fixed getSecondMatch test 2019-12-19 11:38:49 +00:00
Oliver foster
64bbd2a9b1 Fixed tests 2019-12-19 11:26:52 +00:00
Oliver foster
3cdfd7de02 Expanded test coverage for utils.js 2019-12-19 11:22:40 +00:00
Oliver foster
a54868776d Fixed linting issues 2019-12-19 10:51:30 +00:00
Oliver foster
e55055534f Fix travis errors 2019-12-19 10:45:33 +00:00
Oliver foster
97aa1e1972 Fix travis warnings 2019-12-19 10:36:51 +00:00
Oliver foster
d0dfa37e50 Added fallback to native functions 2019-12-19 10:12:52 +00:00
Oliver Foster
066f665aac
Changed bad code 2019-12-19 10:05:29 +00:00
Oliver foster
f5a908584c fixes #359 IE11 Added Array.prototype.find and Object.assign polyfills 2019-12-19 10:02:14 +00:00
Alex Hinds
9c3fc30c81 fix: update types to include constants 2019-12-19 17:05:56 +11:00
zhaoxiaohai
adde31f807 add windowswechat ua 2019-12-17 16:24:04 +08:00
Joseph Culbert
b213e4c8a6 Correctly detect Firefox on iPad 2019-12-13 16:40:59 -06:00
Farfurix
648daa5f9f Add Electron 2019-12-04 15:55:36 +03:00
Denis Demchenko
ea8d9c5427
npm i → npm ci 2019-10-02 21:50:47 +03:00
Denis Demchenko
d95fe87b06 Merge branch '2.7.0' into production 2019-10-02 21:47:13 +03:00
Denis Demchenko
4d66cad51e Merge tag '2.7.0'
2.7.0 2.7.0
2019-10-02 21:47:13 +03:00
Denis Demchenko
41384109cb chore(changelog): write changelog 2019-10-02 21:46:12 +03:00
Denis Demchenko
715ea30809 chore(package): bump version, update deps 2019-10-02 21:44:30 +03:00
Denis Demchenko
935d30f144
Merge pull request #346 from lancedikson/greenkeeper/eslint-plugin-ava-8.0.0
Update eslint-plugin-ava to the latest version 🚀
2019-10-02 21:30:41 +03:00
Denis Demchenko
a50efff25c
Merge pull request #350 from lancedikson/dependabot/npm_and_yarn/mixin-deep-1.3.2
chore(deps): bump mixin-deep from 1.3.1 to 1.3.2
2019-10-02 21:30:12 +03:00
Denis Demchenko
0ce5a8173a
Merge pull request #363 from navarroaxel/feat/gsa
feat(browsers): Add Google Search App detection
2019-10-02 21:26:25 +03:00
Denis Demchenko
bd2918e20e
Merge pull request #364 from lancedikson/greenkeeper/testem-3.0.0
Update testem to the latest version 🚀
2019-10-02 21:24:42 +03:00
Denis Demchenko
493c4fb2e7
Merge pull request #362 from kialo/support-qq-browser
Support QQ Browser
2019-10-02 21:13:43 +03:00
greenkeeper[bot]
23156b429b
chore(package): update lockfile package-lock.json 2019-09-30 17:44:59 +00:00
greenkeeper[bot]
1caea71a81
chore(package): update testem to version 3.0.0 2019-09-30 17:44:54 +00:00
Axel Navarro
e29357793a feat(browsers): Add Google Search App detection 2019-09-25 08:58:27 -03:00
jess
86465cf2ef
Update package.json
removed Open Collective postinstall
2019-09-24 06:52:58 -07:00
Mathias Kahl
e57c3d99d5 support QQ Browser 2019-09-18 10:34:14 +02:00
Jess
2b63c8c7b9 Added call to donate after npm install (optional) 2019-09-14 13:24:48 -07:00
Jess
16778c720d Added financial contributors to the README 2019-09-14 13:24:48 -07:00
Denis Demchenko
ea2f5254e0 Merge branch '2.6.1' into production 2019-09-10 19:04:43 +03:00
Denis Demchenko
bc2d51a8f9 Merge tag '2.6.1'
2.6.1 2.6.1
2019-09-10 19:04:43 +03:00
Denis Demchenko
94a58a2d80 2.6.1 2019-09-10 19:04:13 +03:00
Denis Demchenko
4f12f6bafd chore(package): expose pkg.browser
related to #355
2019-09-10 19:02:13 +03:00
Denis Demchenko
e0cabfeb29 Merge branch '2.6.0' into production 2019-09-06 14:35:38 +03:00
Denis Demchenko
9d4624b29a Merge tag '2.6.0'
2.6.0 2.6.0
2019-09-06 14:35:38 +03:00
Denis Demchenko
b8ef17a7ba chore(package): write changelog, bump version 2019-09-06 14:35:23 +03:00
Denis Demchenko
d9885c9de3 fix(platform): fix Tablet PC detection as tablets
fixes #334
2019-09-06 14:33:14 +03:00
Denis Demchenko
d09b91a4ca
Merge pull request #354 from Gudahtt/add-module-field
Add 'module' field to manifest
2019-09-06 12:33:55 +03:00
Mark Stacey
4356c0a503 Add 'module' field to manifest
The 'module' field is used by bundlers such as rollup and webpack to
determine the entrypoint for a package. Conventionally 'module' is used
for the ES6 entrypoint, and 'main' is used for the CommonJS entrypoint.

Adding a 'module' field allows importing bowser as an ES6 module
directly, rather than using a package-relative path to the ES6
entrypoint (e.g. `bowser/src/bowser`)

Closes #353
2019-09-05 18:28:47 -03:00
dependabot[bot]
5045e25f38
chore(deps): bump mixin-deep from 1.3.1 to 1.3.2
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-09-02 15:55:39 +00:00
Denis Demchenko
810adc38b8 Merge branch '2.5.4' into production 2019-09-02 18:53:44 +03:00
Denis Demchenko
9791ffeaf6 Merge tag '2.5.4'
2.5.4 2.5.4
2019-09-02 18:53:44 +03:00
Denis Demchenko
609bf4a82d chore(changelog): fix changelog 2019-09-02 18:53:28 +03:00
Denis Demchenko
a450ae2510 chore(package): bump version 2019-09-02 18:52:35 +03:00
Denis Demchenko
ab683707f8 chore(building): ignore docs in npm 2019-09-02 18:52:08 +03:00
Denis Demchenko
8fb6e3a080
Update nodejs.yml 2019-08-27 20:17:55 +03:00
dependabot[bot]
3788cea8b1
Merge pull request #348 from lancedikson/dependabot/npm_and_yarn/eslint-utils-1.4.2 2019-08-27 17:17:13 +00:00
Denis Demchenko
40c6be6654
Activate github actions 2019-08-27 20:13:33 +03:00
dependabot[bot]
75f928c3bf
chore(deps): bump eslint-utils from 1.4.0 to 1.4.2
Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.4.0...v1.4.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-27 07:28:43 +00:00
greenkeeper[bot]
19da3c6ab9
chore(package): update lockfile package-lock.json 2019-08-18 12:58:33 +00:00
greenkeeper[bot]
b548f9fed2
chore(package): update eslint-plugin-ava to version 8.0.0 2019-08-18 12:58:29 +00:00
Denis Demchenko
642fd6164f
Update README.md 2019-08-06 14:19:35 +03:00
Denis Demchenko
594b5be6c7 Merge tag '2.5.3'
2.5.3
2019-08-04 23:57:22 +03:00
Denis Demchenko
e7286a5f0f Merge branch '2.5.3' into production 2019-08-04 23:57:15 +03:00
Denis Demchenko
08ae6a0940 chore(changelog): write changelog 2019-08-04 23:56:41 +03:00
Denis Demchenko
b71ed32c70 chore(docs): regenerate docs 2019-08-04 23:53:47 +03:00
Denis Demchenko
1cf7c85f02 chore(.npmignore): ignore .github folder 2019-08-04 23:51:50 +03:00
Denis Demchenko
71d4904d20 chore(.github): move github related files 2019-08-04 23:51:07 +03:00
Denis Demchenko
ee8989bc20 chore(package): bump version to 2.5.3 2019-08-04 23:50:01 +03:00
Denis Demchenko
459754c745
Merge pull request #344 from lancedikson/dependabot/npm_and_yarn/lodash-4.17.15
chore(deps): bump lodash from 4.17.11 to 4.17.15
2019-08-04 23:34:41 +03:00
dependabot[bot]
f35b3d0a55
chore(deps): bump lodash from 4.17.11 to 4.17.15
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.15.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.15)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-04 20:30:14 +00:00
Denis Demchenko
b9ccf3124a
Merge pull request #343 from lancedikson/greenkeeper/webpack-4.39.1
Greenkeeper/webpack 4.39.1
2019-08-04 23:28:44 +03:00
greenkeeper[bot]
b43ffced81 chore(package): update lockfile package-lock.json 2019-08-02 12:48:51 +00:00
greenkeeper[bot]
4f6e7fa14b chore(package): update webpack to version 4.39.1 2019-08-02 12:48:38 +00:00
Denis Demchenko
181eb40357
Merge pull request #338 from joergleis/master
Update OS version names
2019-07-31 23:36:41 +03:00
Denis Demchenko
152ac45f57
Merge pull request #341 from DarkPurple141/patch-1
Update package.json to point to "types"
2019-07-31 23:34:34 +03:00
Alex Hinds
c6c4234f87
Update package.json to to point to "types" 2019-07-30 11:18:59 +10:00
Denis Demchenko
d9b7373f3e
Merge pull request #340 from nepa/patch-1
Update README.md
2019-07-19 18:11:54 +03:00
Jörg Leis
496136fd83 Fixes, refactor, new test cases 2019-07-17 17:33:48 +02:00
NetPanther
c1edead81e
Update README.md
Fixed syntax errors in example
2019-07-17 17:18:17 +02:00
Denis Demchenko
1d613f6227 Merge branch '2.5.2' into production 2019-07-17 16:49:44 +03:00
Denis Demchenko
cb85a7fc2f Merge tag '2.5.2'
2.5.2 2.5.2
2019-07-17 16:49:44 +03:00
Denis Demchenko
2696876747 chore(changelog): write changelog 2019-07-17 16:49:19 +03:00
Denis Demchenko
8ec03334a6 chore(package): bump package version 2019-07-17 16:48:23 +03:00
Denis Demchenko
3639f1ae31 fix(babelrc): fix bundling from auto modules to cjs 2019-07-17 16:47:44 +03:00
Jörg Leis
b2b36e6adb Add unit test for OS version names 2019-07-17 14:13:17 +02:00
Jörg Leis
b298e8d866 Add detection of macOS version names 2019-07-17 13:53:31 +02:00
Jörg Leis
72b59a9208 Add Android Pie to version names 2019-07-17 12:54:43 +02:00
Denis Demchenko
29d1264dcc Merge branch '2.5.1' into production 2019-07-17 13:53:11 +03:00
Denis Demchenko
39f3e3c296 Merge tag '2.5.1'
2.5.1 2.5.1
2019-07-17 13:53:11 +03:00
Denis Demchenko
cd378adf89 chore(docs): auto-generate docs 2019-07-17 13:52:54 +03:00
Denis Demchenko
7cf7777b1b chore(changelog): write changelog 2019-07-17 13:52:07 +03:00
Denis Demchenko
9ba7a45c3f chore(package): bump package version 2019-07-17 13:49:27 +03:00
Denis Demchenko
1515ecaa22 fix(bowser): remove custom error due to the bug (#335) 2019-07-17 13:47:55 +03:00
Denis Demchenko
6de4c21220 chore(babelrc): changes modules and uses loose mode for the build 2019-07-17 13:47:55 +03:00
Denis Demchenko
1d26bea4e9 chore(gitignore): ignore .gz files 2019-07-17 13:47:55 +03:00
Denis Demchenko
fb776cf92a chore(deps): adds compression-webpack-plugin 2019-07-17 13:47:55 +03:00
Denis Demchenko
ac1ec4a6c3 Add webpack-bundle-analyzer 2019-07-17 13:47:55 +03:00
Denis Demchenko
f5c939518e
fix(docs): fix mistypo in README.md 2019-07-16 23:49:15 +03:00
Denis Demchenko
5fc17b73a0 Merge branch 'release/2.5.0' into production 2019-07-16 22:28:15 +03:00
Denis Demchenko
b16fc7135f Merge tag 'release/2.5.0'
2.5.0 release/2.5.0
2019-07-16 22:28:15 +03:00
Denis Demchenko
fb19176de5 chore(changelog): write changelog 2019-07-16 22:24:28 +03:00
Denis Demchenko
f6aa3c7aac chore(package): bump package version 2019-07-16 22:21:40 +03:00
Denis Demchenko
f3c6029f0f docs(bowser): auto-generate docs 2019-07-16 22:21:01 +03:00
Denis Demchenko
dcadd16ed7 docs(bowser): improve some JSDocs and Error class 2019-07-16 22:19:07 +03:00
Denis Demchenko
41b66d5450 refactor(bowser): replace static properties with getters 2019-07-16 22:00:28 +03:00
Denis Demchenko
94530f010e chore(npm-scripts): rename some npm scripts 2019-07-16 21:56:06 +03:00
Denis Demchenko
ec7aeac08c Add information about funding to Readme 2019-07-16 21:39:38 +03:00
Denis Demchenko
976518e524 Add FUNDING.yml 2019-07-16 21:39:38 +03:00
Denis Demchenko
2c5d1282d7 Update the header of README.md 2019-07-16 21:39:38 +03:00
Denis Demchenko
85f69b9dfb
Merge pull request #333 from lancedikson/dependabot/npm_and_yarn/lodash-4.17.14
Bump lodash from 4.17.11 to 4.17.14
2019-07-16 21:18:17 +03:00
Denis Demchenko
e9cb529da8 Use node 12 on TravisCI 2019-07-16 21:15:26 +03:00
dependabot[bot]
3368012af1
Bump lodash from 4.17.11 to 4.17.14
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-16 18:14:53 +00:00
Denis Demchenko
e7fe551d0c Merge branch 'greenkeeper/eslint-6.0.1' 2019-07-16 21:09:46 +03:00
Denis Demchenko
de0fe99ac7 Update all dependencies 2019-07-16 21:07:51 +03:00
greenkeeper[bot]
683f4934ad chore(package): update lockfile package-lock.json 2019-07-16 21:01:55 +03:00
greenkeeper[bot]
b0b94839f9 chore(package): update eslint to version 6.0.1
Closes #331
2019-07-16 21:01:55 +03:00
Denis Demchenko
c92f9978eb
Merge pull request #328 from lancedikson/greenkeeper/eslint-plugin-ava-7.0.0
Update eslint-plugin-ava to the latest version 🚀
2019-07-16 20:54:32 +03:00
Denis Demchenko
1398d94d59
Merge pull request #327 from lancedikson/greenkeeper/ava-2.0.0
Update ava to the latest version 🚀
2019-07-16 20:53:46 +03:00
Denis Demchenko
a2a8f10fd4
Merge pull request #332 from thewizarodofoz/master
adding detection for Roku OS
2019-07-12 11:40:14 +03:00
Oz Weiss
82cd6a82de adding detection for Roku OS: https://en.wikipedia.org/wiki/Roku#Software
examples: http://www.webapps-online.com/online-tools/user-agent-strings/dv/brand798903/roku-dvp

note: The reason I added the test for Roku before all other tests is that Roku user agents might contain other tokens (like Windows), but Roku is still Roku.
2019-07-07 12:55:53 +03:00
greenkeeper[bot]
c124acee9e chore(package): update lockfile package-lock.json 2019-06-01 12:19:15 +00:00
greenkeeper[bot]
53d5ba413a chore(package): update eslint-plugin-ava to version 7.0.0 2019-06-01 12:19:11 +00:00
greenkeeper[bot]
59c9bc34f4 chore(package): update lockfile package-lock.json 2019-06-01 12:13:00 +00:00
greenkeeper[bot]
9be5565daf chore(package): update ava to version 2.0.0 2019-06-01 12:12:55 +00:00
Denis Demchenko
41bbfc1600
Merge pull request #325 from 1615450788/master
Add constant output so that users can quickly get all types
2019-05-27 00:44:08 +03:00
王涛
fbc32e6736 Add constant output so that users can quickly get all types 2019-05-20 15:33:10 +08:00
Denis Demchenko
5a6dcc2899 Merge branch '2.4.0' into production 2019-05-03 21:51:38 +03:00
Denis Demchenko
f567ab3ec2 Merge tag '2.4.0'
2.4.0 2.4.0
2019-05-03 21:51:38 +03:00
Denis Demchenko
d160acaf12 Update documents 2019-05-03 21:50:41 +03:00
Denis Demchenko
2dc08c0da7 Bump version, update changelog 2019-05-03 21:50:09 +03:00
Denis Demchenko
86152dac82 Fixes docs
fixes #320
2019-05-03 21:40:55 +03:00
Denis Demchenko
2ed80a5074 Merge branch 'pull/322'
# Conflicts:
#	package-lock.json
2019-05-03 21:36:38 +03:00
Denis Demchenko
5a00bec733 Merge branch 'pull/321'
# Conflicts:
#	package-lock.json
2019-05-03 21:32:00 +03:00
Denis Demchenko
707c5982af
Merge pull request #316 from lancedikson/greenkeeper/nyc-14.0.0
Update nyc to the latest version 🚀
2019-05-03 21:20:28 +03:00
Denis Demchenko
e1a37ef4fa
Merge pull request #310 from ricardorauber/master
Update the regexp for generic browsers
2019-04-24 21:28:27 +03:00
Denis Demchenko
b9078b8862
Merge pull request #318 from DasRed/master
fixing ES6 Module import for BROWSER_ALIAS_MAP
2019-04-24 21:27:57 +03:00
Ricardo Rauber Pereira
b8d60f7593 fix regexp selection order 2019-04-23 10:40:04 +01:00
Ricardo Rauber Pereira
2dcfca1388 remove tabs 2019-04-23 10:28:11 +01:00
Ricardo Rauber Pereira
d0959a43c4 update the constant names 2019-04-23 10:15:02 +01:00
Ricardo Rauber Pereira
8e49696d02 update the comment 2019-04-23 10:13:52 +01:00
Ricardo Rauber Pereira
4d8c781369 updated the code to be more clear 2019-04-23 10:11:04 +01:00
Marco Starker
11f3ae7009 spaces 2019-04-21 21:40:57 +02:00
Marco Starker
23c640f65f 🙄 2019-04-21 08:21:00 +02:00
Denis Demchenko
18881fdd97 Make prefer-default-export rule warning 2019-04-18 21:33:45 +03:00
Marco Starker
98f348ebd3 switching from default export to named export 2019-04-18 16:09:16 +02:00
Marco Starker
7075f6c4d7 adding useless semicolon 2019-04-18 13:50:17 +02:00
Marco Starker
0f20a43f0a fixing ES6 Module import for BROWSER_ALIAS_MAP 2019-04-18 13:46:30 +02:00
greenkeeper[bot]
9db55c93ed chore(package): update lockfile package-lock.json 2019-04-17 17:19:04 +00:00
greenkeeper[bot]
cd4eda8814 chore(package): update babel-plugin-add-module-exports to version 1.0.2 2019-04-17 17:19:00 +00:00
greenkeeper[bot]
2830825613 chore(package): update lockfile package-lock.json 2019-04-16 21:40:07 +00:00
greenkeeper[bot]
71b1384057 chore(package): update eslint-plugin-import to version 2.17.2 2019-04-16 21:40:01 +00:00
greenkeeper[bot]
b119b7aeb0 chore(package): update lockfile package-lock.json 2019-04-16 10:22:02 +00:00
greenkeeper[bot]
a4712097f8 chore(package): update nyc to version 14.0.0 2019-04-16 10:21:58 +00:00
Denis Demchenko
b55b0bb540 Merge tag '2.3.0'
2.3.0 2.3.0
2019-04-14 13:46:50 +03:00
Denis Demchenko
c81399a82d Merge branch '2.3.0' into production 2019-04-14 13:46:49 +03:00
Denis Demchenko
91ac5e2018 Update docs 2019-04-14 13:45:57 +03:00
Denis Demchenko
5206d0e837 Write changelog 2019-04-14 13:45:30 +03:00
Denis Demchenko
484a007aad Bump version to 2.3.0 2019-04-14 13:42:40 +03:00
Denis Demchenko
d596a43f6b Add support of the new Blink-based MS Edge
fixes #311
2019-04-14 13:39:35 +03:00
Denis Demchenko
5c47015b6b
Merge pull request #289 from JaceHensley/feat/improve-types/dev
Export Parser types
2019-04-14 13:18:21 +03:00
Denis Demchenko
58f4166814 Merge branch 'pull/297'
# Conflicts:
#	package-lock.json
#	package.json
2019-04-14 13:08:00 +03:00
Denis Demchenko
78e9f09a8b Merge branch 'pull/305'
# Conflicts:
#	package-lock.json
2019-04-14 13:02:55 +03:00
Denis Demchenko
7ae67fd601 Update dependecies in order to fix vulnarabilities 2019-04-14 12:58:54 +03:00
Denis Demchenko
d3046bf63e Merge branch 'hotfix/2.2.1' into production 2019-04-12 21:46:51 +03:00
Denis Demchenko
16a4936f47 Merge tag '2.2.1'
no message
2019-04-12 21:46:51 +03:00
Denis Demchenko
51d8b0f3ea Bump version, write changelog 2019-04-12 21:46:17 +03:00
Denis Demchenko
328852aa0e Add an alias for Samsung Internet
related to #313
2019-04-12 21:43:09 +03:00
Denis Demchenko
8212e48e02 Add tests for a browser without an alias 2019-04-12 21:35:17 +03:00
Denis Demchenko
4b658441ca Add docs for Parser#isBrowser 2019-04-12 21:06:09 +03:00
Denis Demchenko
69972820c8 Fix the bug with unset alias for a browser
fix #313
2019-04-12 21:05:14 +03:00
Denis Demchenko
1d66cb9e89 Merge branch 'release/2.2.0' into production 2019-04-07 11:48:36 +03:00
Denis Demchenko
5200773ca7 Merge tag '2.2.0'
no message
2019-04-07 11:48:36 +03:00
Denis Demchenko
6cc8c84c56 Rebuild docs 2019-04-07 11:48:26 +03:00
Denis Demchenko
91f0e8936d Bump version 2019-04-07 11:48:04 +03:00
Denis Demchenko
09b73d7897 Update changelog and readme 2019-04-07 11:43:06 +03:00
Denis Demchenko
428dadc503 Fix Yandex Browser version detection
fixes #308
2019-04-07 11:28:03 +03:00
Denis Demchenko
19288762f1
Merge pull request #295 from willamesoares/master
Add support for using short version for browser name in satisfies
2019-04-07 11:07:57 +03:00
Ricardo Rauber Pereira
42b0f185e2 Change test os and platform 2019-04-05 18:39:25 +01:00
Ricardo Rauber Pereira
cfe2b493bb Remove missing space at the end 2019-04-05 18:33:15 +01:00
Ricardo Rauber Pereira
3bfb24c8cb Updated the check for generic browsers 2019-04-05 18:18:39 +01:00
Ricardo Rauber Pereira
f1bdd50116 Update test for Generic browser 2019-04-05 17:58:30 +01:00
Ricardo Rauber Pereira
ba4783868d Update the regex for custom browsers 2019-04-05 17:43:04 +01:00
greenkeeper[bot]
28b6f13879 chore(package): update lockfile package-lock.json 2019-03-24 16:18:06 +00:00
greenkeeper[bot]
7488c4f61e chore(package): update eslint-plugin-ava to version 6.0.0 2019-03-24 16:18:02 +00:00
Will Soares
ace7a8899b Fix eslint errors 2019-03-09 19:29:34 -03:00
Will Soares
b111862cce Update rules for creating browser aliases 2019-03-09 19:27:28 -03:00
Will Soares
064aa812fc Use snake case for alias names 2019-03-09 19:14:03 -03:00
Will Soares
a307533f74 Add support for using short version for browser name in satisfies 2019-03-09 19:14:03 -03:00
Denis Demchenko
d57235b423 Merge branch 'hotfix/2.1.2' into production 2019-03-06 14:40:34 +02:00
Denis Demchenko
28bff841b3 Merge tag '2.1.2'
no message
2019-03-06 14:40:34 +02:00
Denis Demchenko
9bc8b31d23 Bump version, write changelog 2019-03-06 14:40:28 +02:00
Denis Demchenko
31adae6a59 Remove buggy getFirstMatch reference 2019-03-06 14:39:21 +02:00
Denis Demchenko
2a847c7336 Merge branch 'release/2.1.1' 2019-03-06 14:33:28 +02:00
Denis Demchenko
c3c986c143 Merge branch 'release/2.1.1' into production
# Conflicts:
#	src/parser-os.js
2019-03-06 14:32:17 +02:00
Denis Demchenko
58a871b5da Update docs 2019-03-06 14:31:37 +02:00
Denis Demchenko
bf69678f86 Bump version, write chagelog 2019-03-06 14:30:40 +02:00
Denis Demchenko
134ef3c186 Fix bugs with Utils 2019-03-06 14:27:35 +02:00
Denis Demchenko
5873e24c76
Merge pull request #301 from nicgirault/patch-1
Clarify use case in doc
2019-03-06 14:20:48 +02:00
rcohen-unext
383c627fc0 Add PlayStation 4 browser support 2019-03-06 14:19:34 +02:00
Nicolas Girault
3fdde501d4
Clarify use case in doc
close #300
2019-03-05 22:06:02 +01:00
Denis Demchenko
a81b8c0ed7
Merge pull request #294 from FostUK/es6-import-extensions
Add file extensions to imports
2019-03-02 16:31:39 +02:00
Denis Demchenko
bc8d932598
Merge pull request #293 from SterlingVix/master
Deploy docs to GH Pages
2019-02-24 18:53:23 +02:00
greenkeeper[bot]
af6ead8086 chore(package): update lockfile package-lock.json 2019-02-18 15:36:58 +00:00
greenkeeper[bot]
17afb1c9ea chore(package): update sinon to version 7.2.4 2019-02-18 15:36:54 +00:00
Nick Tipping
bf067ec992 Add file extensions to imports
Add ES6 style export to utils and change related utils imports
Update eslint rule for import extensions
2019-02-14 16:06:14 +00:00
Aaron Melocik
b576932d0e Update README. Add gh-pages docs link. 2019-02-13 19:54:35 -08:00
Aaron Melocik
a2da1fa5be Add gh-pages deploy script. 2019-02-13 19:41:45 -08:00
Aaron Melocik
ebed45124b initial commit 2019-02-13 19:36:19 -08:00
Denis Demchenko
b986897ff8
Merge pull request #291 from rcohen-unext/production
Add PlayStation 4 browser support
2019-02-09 11:50:07 +02:00
Denis Demchenko
91fa272785
Merge pull request #290 from lancedikson/greenkeeper/nyc-13.2.0
Update nyc to the latest version 🚀
2019-02-09 11:48:38 +02:00
rcohen-unext
dcbb0a51dd Add PlayStation 4 browser support 2019-02-06 17:47:28 +09:00
greenkeeper[bot]
ddd80d99b0 chore(package): update lockfile package-lock.json 2019-02-05 04:09:55 +00:00
greenkeeper[bot]
272e7b58a7 chore(package): update nyc to version 13.2.0 2019-02-05 04:09:51 +00:00
Jace
96510405be
Export Parser types
- Move the Parser namespace into the Bowser namespace
- Make the Parser class an interface so consumers can't construct a Parser class (this is not exported by bowser)
2019-01-30 16:20:56 -07:00
Denis Demchenko
943adfb581 Merge branch 'release/2.1.0' into production 2019-01-24 23:06:13 +02:00
Denis Demchenko
13e178ccce Merge tag '2.1.0'
no message
2019-01-24 23:06:13 +02:00
Denis Demchenko
a8900397b2 Bump version, write changelog 2019-01-24 23:06:07 +02:00
Denis Demchenko
747059a49d
Merge pull request #288 from ffaubert/add-engine-api
Add getEngineName and isEngine API calls
2019-01-24 22:44:29 +02:00
Denis Demchenko
382177f8e5
Merge pull request #287 from ffaubert/detect-chromeos
Add operating system detection for Chrome OS
2019-01-24 22:43:20 +02:00
Frank Faubert
83e8f61109 Add getEngineName and isEngine API calls 2019-01-24 09:04:37 -05:00
Frank Faubert
65988ac79c Add operating system detection for Chrome OS 2019-01-24 08:37:59 -05:00
Denis Demchenko
c5d18a4db9
Merge pull request #284 from JBallin/readme-import-instructions
Update instructions to use default import
2019-01-22 21:07:07 +02:00
Denis Demchenko
3b2fa910d0
Merge pull request #283 from JBallin/readme-to-contrib
Move contribution instructions from README to CONTRIBUTING
2019-01-22 21:06:23 +02:00
Denis Demchenko
2949f37127
Merge pull request #282 from JBallin/readme-capitalize-bowser
Capitalize imported Bowser object
2019-01-22 21:05:03 +02:00
JBallin
73be17508d Add ES6 import example 2019-01-22 09:09:48 -08:00
JBallin
fed702a148 Fix 'TypeScript' capitalization and add missing semicolon 2019-01-22 09:08:50 -08:00
JBallin
86f8f63e50 Improve CONTRIBUTING.md 2019-01-21 14:22:44 -08:00
JBallin
e87ce75599 Move contribution instructions from README to CONTRIBUTING 2019-01-21 14:21:46 -08:00
JBallin
7fcca781f0 Capitalize imported Bowser object 2019-01-21 11:14:22 -08:00
Denis Demchenko
700732f7b3
Merge pull request #281 from alexandercerutti/master
Fixed typings indentation and edited readme
2019-01-20 19:05:02 +02:00
Alexander Cerutti
c882d03ad4
Fixed broken indentation for typings 2019-01-19 16:42:58 +01:00
Alexander Cerutti
b804285d5c
Removed alpha version reference in the readme 2019-01-19 16:39:05 +01:00
Denis Demchenko
4ec19a2462 Merge branch 'release/2.0.0' into production 2019-01-19 16:03:00 +02:00
Denis Demchenko
122d4a96c0 Merge tag '2.0.0'
no message
2019-01-19 16:03:00 +02:00
Denis Demchenko
df6183ff8e Fix readme 2019-01-19 16:01:30 +02:00
Denis Demchenko
87eb7a9581 Fix contributing docs 2019-01-19 15:57:00 +02:00
Denis Demchenko
486fcffdc1 Bump version 2019-01-19 15:54:02 +02:00
Denis Demchenko
c448439b73 Write changelog for 2.0.0 2019-01-19 15:53:06 +02:00
Denis Demchenko
a87ccad88a Fix the docs 2019-01-19 15:44:08 +02:00
Denis Demchenko
cab0d0d946 Fix an issue with returning a reference instead of a new object 2019-01-19 15:43:29 +02:00
Denis Demchenko
3954c8b0df Update babel-plugin-istanbul and webpack-cli 2019-01-19 12:59:11 +02:00
greenkeeper[bot]
2bf4f63c48 chore(package): update lockfile package-lock.json 2019-01-19 12:51:07 +02:00
greenkeeper[bot]
23a8114277 chore(package): update webpack to version 4.28.4 2019-01-19 12:50:07 +02:00
greenkeeper[bot]
051a377a78 chore(package): update lockfile package-lock.json 2019-01-19 12:46:51 +02:00
greenkeeper[bot]
67c6db946c chore(package): update babel-loader to version 8.0.5
Closes #258
2019-01-19 12:34:50 +02:00
greenkeeper[bot]
15fb64f562 chore(package): update lockfile package-lock.json 2019-01-19 12:20:55 +02:00
greenkeeper[bot]
b0ee595a91 chore(package): update babel-eslint to version 10.0.1
Closes #257
2019-01-19 12:18:43 +02:00
Denis Demchenko
9d2d93ebd4 Upgrade ava to 1.1.0 and fix tests 2019-01-19 12:07:15 +02:00
greenkeeper[bot]
1a15ccdbea chore(package): update lockfile package-lock.json 2019-01-19 11:56:16 +02:00
greenkeeper[bot]
8a57914a84 chore(package): update ava to version 1.1.0
Closes #273
2019-01-19 11:56:16 +02:00
Denis Demchenko
b2d641e647 Fix nyc config to exclude built files from coverage 2019-01-19 11:49:28 +02:00
Denis Demchenko
dedbe9f199
Merge pull request #278 from rcsandell/master
Added support for Googlebot recognition
2019-01-17 11:45:10 +02:00
Denis Demchenko
5a3b5090ee
Merge pull request #277 from alexandercerutti/master
Added typings for v2
2019-01-17 11:41:31 +02:00
Robert Sandell
1535c62b74 Added support for Googlebot recognition 2019-01-16 13:30:38 +02:00
Alexander Cerutti
35814130fd
Updated Readme upon the changes to typings 2019-01-15 09:43:08 +01:00
Alexander Cerutti
93e1ff52aa
Added a definitive-working definition for v2 2019-01-15 09:42:23 +01:00
Alexander Cerutti
e17180a6a8
Updated Readme to include typescript import 2019-01-11 23:41:59 +01:00
Alexander Cerutti
3d63c268f4
Update .travis.yml
Updated travis.yml to execute run-script build
2019-01-10 00:34:21 +01:00
Alexander Cerutti
2c13c9a528
Update package.json
Issue #229 about npm deprecation note fix
2019-01-10 00:07:06 +01:00
Alexander Cerutti
399d64a5a8
Added typings for v2 2019-01-08 11:32:06 +01:00
Denis Demchenko
1085ae62ad Fix failing tests 2019-01-07 00:23:01 +02:00
Denis Demchenko
cd72625e2c
Merge pull request #276 from rcsandell/master
Support Android version names, Recognise Huawei devices
2019-01-06 22:40:40 +02:00
Denis Demchenko
d39f2fe125
Merge pull request #275 from deployed/master
Support non strict equality in satisfies method
2019-01-06 22:38:11 +02:00
Denis Demchenko
7b8ea93d22
Merge pull request #260 from ycjcl868/feat-wechat-browser
feat: wechat browser support
2019-01-06 22:27:08 +02:00
Robert Sandell
cce6430647 Mention running lint rules, conform commit to lint rules 2018-12-30 10:31:13 +02:00
Robert Sandell
97d877f9c2 Fix Travis Tests 2018-12-30 10:18:58 +02:00
Robert Sandell
d9693088cc Fix tests 2018-12-30 10:10:33 +02:00
Robert Sandell
f338045df7 Support Android version names, Recognise Huawei devices 2018-12-30 09:03:08 +02:00
Dariusz Rzepka
3729f6f92e Support non strict equality in satisfies method 2018-12-28 08:36:32 +01:00
Denis Demchenko
70a4604873
Merge pull request #261 from aknuds1/bugfix/fix-docs
Improve documentation language, fix an example
2018-10-23 12:42:06 +03:00
Arve Knudsen
316399d6e9 Improve documentation language, fix an example 2018-10-19 19:32:59 +02:00
ycjcl868
1ce9916b35 feat: wechat browser 2018-10-14 23:25:45 +08:00
Denis Demchenko
be6a7b2d41 Merge tag '2.0.0-beta.3' into develop
no message
2018-09-15 14:36:56 +03:00
Denis Demchenko
6bde5e128f Merge branch 'hotfix/2.0.0-beta.3' 2018-09-15 14:36:56 +03:00
Denis Demchenko
21bccb1bf2 Bump version, write changelog 2018-09-15 14:36:48 +03:00
Denis Demchenko
c0cfe887a9 Use built for CI
closes #252
2018-09-15 14:31:39 +03:00
Denis Demchenko
33146299dc Merge branch 'greenkeeper/babel-plugin-add-module-exports-1.0.0' 2018-09-14 17:44:37 +03:00
Denis Demchenko
0a149bca7b Fix Chrome mobile detection
fixes #253
2018-09-14 17:44:17 +03:00
greenkeeper[bot]
f8b0765e74 chore(package): update babel-plugin-add-module-exports to version 1.0.0 2018-09-11 06:29:47 +00:00
Denis Demchenko
1158fe9ff6 Merge tag '2.0.0-beta.2' into develop
no message
2018-09-09 15:13:15 +03:00
Denis Demchenko
4a4e41ccf8 Merge branch 'release/2.0.0-beta.2' 2018-09-09 15:13:15 +03:00
Denis Demchenko
8fbdaa4f3a Bump version, write changelog 2018-09-09 15:13:08 +03:00
Denis Demchenko
7c411be476 Regen docs 2018-09-09 15:08:48 +03:00
Denis Demchenko
3489f9d374 Support Swing browser
fixes #248
2018-09-09 15:07:40 +03:00
Denis Demchenko
ace0ce17ea Fix the issue with undefined browser version string
fixes #243
2018-09-09 15:02:29 +03:00
Denis Demchenko
19af6a8f2e Separate eslint check from test command 2018-09-09 14:01:45 +03:00
Denis Demchenko
c04942947e Fix no-else-return issue 2018-09-09 13:52:41 +03:00
Denis Demchenko
7e10b20aba Use babel-eslint as parser for eslint 2018-09-09 13:27:02 +03:00
Denis Demchenko
8af2e682a2 Fix travis testing (include eslint) 2018-09-09 13:25:07 +03:00
Denis Demchenko
5ef075160b Update deps 2018-09-09 12:58:25 +03:00
Denis Demchenko
ee165ed9e7 Merge branch adblockplus/master into develop 2018-09-09 12:24:58 +03:00
Denis Demchenko
c62767ec36 Merge branch 'greenkeeper/initial' into develop 2018-09-09 12:23:59 +03:00
Julian Doucette
343b748986 Added maxthon desktop support 2018-08-29 22:44:50 +01:00
greenkeeper[bot]
f720e539f3 docs(readme): add Greenkeeper badge 2018-08-24 22:06:25 +00:00
greenkeeper[bot]
84886ca142 chore(package): update dependencies 2018-08-24 22:04:19 +00:00
Denis Demchenko
505f19f207 Merge branch 'release/2.0.0-beta.1' 2018-08-18 14:20:19 +03:00
Denis Demchenko
7891a1f56e Merge tag '2.0.0-beta.1' into develop
no message
2018-08-18 14:20:19 +03:00
Denis Demchenko
486f718c1d Bump version, write changelog 2018-08-18 14:20:11 +03:00
Denis Demchenko
2bc8982b42 Regen docs 2018-08-18 14:14:56 +03:00
Denis Demchenko
d039ce020e Add contributing.md 2018-08-18 14:13:50 +03:00
Denis Demchenko
6434c76184
Merge pull request #241 from udivankin/develop
Adds loose comparison support
2018-08-18 13:59:52 +03:00
udivankin
6204d9f417 Adds loose comparison support 2018-08-16 19:04:10 +03:00
Denis Demchenko
42b4c8cfa3 Merge tag '2.0.0-alpha.4' into develop
no message
2018-08-02 21:51:15 +03:00
Denis Demchenko
2c5ab93a19 Merge branch 'release/2.0.0-alpha.4' 2018-08-02 21:51:14 +03:00
Denis Demchenko
818040b41a Bump version, write changelog 2018-08-02 21:51:02 +03:00
Denis Demchenko
8e919efd4f Make es5.js the main file of the package
fixes #239
2018-08-02 21:47:44 +03:00
Denis Demchenko
2b6a63d088 Fix code style problem 2018-08-02 21:26:47 +03:00
Patrick
af26b08642 Fix getParsers in README.md
getParsers is not a function it is called getParser instead
closes #238
2018-08-02 21:26:47 +03:00
Denis Demchenko
4e6aa12a79 Merge branch 'release/2.0.0-alpha.3' 2018-07-22 19:48:02 +03:00
Denis Demchenko
b7acaf32f5 Merge tag '2.0.0-alpha.3' into develop
no message
2018-07-22 19:48:02 +03:00
Denis Demchenko
594c437de6 Bump version, write changelog 2018-07-22 19:47:56 +03:00
Denis Demchenko
8782a29096 Generate docs 2018-07-22 19:42:46 +03:00
Matías Lescano
0224f26bfc Add parser.some function 2018-07-22 19:41:48 +03:00
Denis Demchenko
2dc858e033 Generate docs 2018-07-22 19:38:52 +03:00
Denis Demchenko
ab299af55f Write a bit about usage of bowser 2018-07-22 19:38:45 +03:00
Denis Demchenko
8e9a6c7b4a Compile 2 versions of files (es5 and bundled) 2018-07-22 19:31:49 +03:00
Denis Demchenko
2ae6ce1820 Merge branch 'release/2.0.0-alpha.2' 2018-07-17 21:27:00 +03:00
Denis Demchenko
3e8152bb18 Merge tag '2.0.0-alpha.2' into develop
no message
2018-07-17 21:27:00 +03:00
Denis Demchenko
dc15bf483e Bump version, update the changelog 2018-07-17 21:26:45 +03:00
Denis Demchenko
8d7ef744ac Fix detection of Nexus devices
fixes #233
2018-07-17 21:21:56 +03:00
Denis Demchenko
8e900bc0a9 Add .npmrc 2018-07-17 21:10:09 +03:00
Denis Demchenko
718bea0016 Update README.md 2018-07-17 19:27:21 +03:00
Denis Demchenko
bdd75028e5 Change the way of compilation and requiring
fixes #231
2018-07-17 19:22:22 +03:00
James Ross
b94587fdbc Improve code formatting in README
closes #230
2018-07-17 19:15:34 +03:00
Denis Demchenko
8ab0b442b6 Remove typings until stable release
fixes #232
2018-07-17 19:13:01 +03:00
Denis Demchenko
51da829e4c Fix dotfiles 2018-07-09 21:48:04 +03:00
Denis Demchenko
7fc8f3cb3b Merge branch 'release/2.0.0-alpha.1' 2018-07-09 21:35:48 +03:00
Denis Demchenko
e91faf7972 Merge tag '2.0.0-alpha.1' into develop
no message
2018-07-09 21:35:48 +03:00
Denis Demchenko
6fa89713e3 Write changelog, bump version 2018-07-09 21:34:00 +03:00
Denis Demchenko
c50a9e2f5f Get rid of bower support 2018-07-09 21:32:28 +03:00
Denis Demchenko
8676817177 Catch up with last browsers in 1.9 version 2018-07-09 21:26:43 +03:00
Denis Demchenko
c89a8d157e Avoid babel debug during building 2018-07-09 21:26:19 +03:00
Denis Demchenko
72c5fd6980 Merge branch 'v2' into develop 2018-07-09 21:04:20 +03:00
Denis Demchenko
b9db96b1b5 Add changelog and a bit of readme.md 2018-07-09 19:14:22 +03:00
Denis Demchenko
f759d7ebf6 Paste existing changelog 2018-07-09 19:07:55 +03:00
Denis Demchenko
4c3489fa00 Make sure that it builds before publishing 2018-07-09 19:05:19 +03:00
Denis Demchenko
44e6a21dde Add a note about alpha stage to README.md 2018-07-09 19:03:11 +03:00
Denis Demchenko
fe977a73b8 Include babel-polyfill into the build 2018-07-08 16:47:40 +03:00
Denis Demchenko
c5f749c3d4 Trying to include needed polyfills into the build 2018-07-08 14:40:48 +03:00
Denis Demchenko
b75dff2b57 Change main file to the building one 2018-07-08 13:25:32 +03:00
Denis Demchenko
5149acc2c5 Add simple webpack builder into the project 2018-07-08 13:20:46 +03:00
Denis Demchenko
0bcb5713cd Remove old typings.d.ts 2018-07-08 12:48:54 +03:00
Denis Demchenko
b536c424d0 Update README.md 2018-07-08 12:45:33 +03:00
Denis Demchenko
31b9240aec Fix docs 2018-07-08 12:31:23 +03:00
Denis Demchenko
3a9c4b3a3d Rebuild documentation 2018-07-08 12:09:27 +03:00
Denis Demchenko
d12a988d7c Rewrite Parser.satisfies and fix some related methods 2018-07-08 12:08:49 +03:00
Denis Demchenko
a175f7c8bd Rename Parser.compare to Parser.satisfies 2018-07-07 18:35:18 +03:00
Denis Demchenko
c79b71736e Fix tests after changes 2018-07-05 22:58:14 +03:00
Denis Demchenko
1f572ed8f4 Add a bit of docs 2018-07-05 22:44:43 +03:00
Denis Demchenko
15b431562b Add use cases to the docs 2018-07-05 21:18:04 +03:00
Denis Demchenko
14ed0ffd46 Fix templates and repo meta information 2018-07-05 10:07:22 +03:00
Denis Demchenko
e759592884 Fix getPlatformType, write tests 2018-07-04 23:09:33 +03:00
Denis Demchenko
48638e7363 Change Parser.check to Parser.compare 2018-07-04 22:43:57 +03:00
Denis Demchenko
0c1564f1cd Fix comments for Bowser class 2018-07-04 22:39:46 +03:00
Denis Demchenko
4ab0d9dfd3 Get rid of semver and use old comparison which is more applicable 2018-07-02 23:30:48 +03:00
Denis Demchenko
6030eb9e5d Add semverCheck and related methods 2018-07-02 22:24:02 +03:00
Denis Demchenko
560ec06eeb Add Parser.check and related things 2018-07-02 16:51:40 +03:00
Denis Demchenko
9cb04fcbae Move getWindowsVersionName to utils 2018-06-30 19:40:10 +03:00
Denis Demchenko
3530ca1c70 Fix nyc misconfiguration 2018-06-30 19:21:09 +03:00
Denis Demchenko
107069b845 Include eslint to npm test 2018-06-30 18:50:05 +03:00
Denis Demchenko
949368cba7 Ignore coverage folder 2018-06-30 18:44:45 +03:00
Denis Demchenko
0ea3fe16a4 Add coveralls integration
fixes #225
2018-06-30 17:35:12 +03:00
Denis Demchenko
48fe1d33cb Add coveralls.yml 2018-06-30 17:29:34 +03:00
Denis Demchenko
e7e6abff8b Fix Bowser constructor, add some tests 2018-06-30 17:25:47 +03:00
Denis Demchenko
98007768b4 Make Parser.parse-anything methods public 2018-06-30 15:58:34 +03:00
Denis Demchenko
1fb99ced0e Merge branch 'hotfix/1.9.4' into production 2018-06-28 21:32:37 +03:00
Denis Demchenko
041fe77ab4 Merge tag '1.9.4'
no message
2018-06-28 21:32:37 +03:00
Denis Demchenko
87aff8ba75 Bump versions, write changelog 2018-06-28 21:32:22 +03:00
Denis Demchenko
49746c5547 Fix webOS detection
fixes #186
2018-06-28 21:31:49 +03:00
Denis Demchenko
6e78874470 Add detection of Firefox Focus
Fixes #191
2018-06-28 21:21:36 +03:00
Denis Demchenko
dbdc014300 Add detection of MZBrowser
fixes #219
2018-06-28 21:13:17 +03:00
Chanhyun,Roh
d4558db0ff fix property-name 'Whale' to 'whale' in README 2018-06-28 20:37:27 +03:00
Chanhyun,Roh
b53cd60e18 define whale in typings.d.ts 2018-06-28 20:37:27 +03:00
Chanhyun,Roh
645f3a95a4 add NAVER Whale browser (based on blink engine) 2018-06-28 20:37:27 +03:00
Denis Demchenko
f202c1cd30 Eslint fixes 2018-06-27 23:11:52 +03:00
Denis Demchenko
6aedccecd4 Update deps 2018-06-27 23:08:54 +03:00
Denis Demchenko
45ac881a5e Fix credits 2018-06-27 23:04:46 +03:00
Denis Demchenko
b299397f08 Update testing and coverage tools 2018-06-27 22:59:32 +03:00
Denis Demchenko
6f3b13f9fd Replace the main bowser file 2018-06-27 22:52:43 +03:00
Denis Demchenko
55f3736414 Merge branch 'hotfix/1.9.3' into production 2018-03-12 22:05:17 +02:00
Denis Demchenko
6bbdaf99f0 Merge tag '1.9.3'
no message
2018-03-12 22:05:17 +02:00
Denis Demchenko
6575e4a0ab Bump version, write changelog 2018-03-12 22:05:10 +02:00
Denis Demchenko
aea9282426 Define iphone, ipad, ipod as flags in typings.d.ts 2018-03-12 22:04:11 +02:00
Ville Kentta
1635cd8607 Add samsungBrowser to browser version typings 2018-03-12 21:55:59 +02:00
Denis Demchenko
290ef0730e Merge branch 'hotfix/1.9.2' 2018-02-05 20:30:42 +02:00
Denis Demchenko
a1f1af1e36 Merge branch 'hotfix/1.9.1' 2017-12-22 17:33:31 +02:00
Denis Demchenko
898d8e32dd Remove old files 2017-12-22 17:24:38 +02:00
Denis Demchenko
ad2589f699 Add eslint support 2017-12-20 23:29:06 +02:00
Denis Demchenko
b1170af9d8 TYPES → TYPES_LABELS 2017-12-20 22:48:23 +02:00
Denis Demchenko
bee21ea5c3 Fix small mistypos 2017-12-20 22:48:05 +02:00
Denis Demchenko
b15544770a Remove old useragents list 2017-12-20 22:47:50 +02:00
Denis Demchenko
778fdb6004 Add Microsoft Edge cases 2017-12-20 22:34:29 +02:00
Denis Demchenko
aec02c2c1b Update deps, add package-lock 2017-12-20 22:14:39 +02:00
Denis Demchenko
d657769e44 Merge branch 'release/1.9.0' 2017-12-20 21:54:06 +02:00
Denis Demchenko
85cf8f8bbb Add some future usage examples 2017-10-18 11:47:53 +03:00
Denis Demchenko
d3fec85440 Fix integration tests
Provided more details for the testing thing
2017-10-17 21:56:09 +03:00
Denis Demchenko
058d5e0774 Fix testing commands 2017-08-20 18:37:01 +03:00
Denis Demchenko
d78f7ee253 Remove npm test from .travis.yml 2017-08-20 18:33:47 +03:00
Denis Demchenko
99f85489e9 Remove old prepublish script 2017-08-20 18:33:21 +03:00
Denis Demchenko
2e3bd8ca80 Fix .travis.yml to use node 8.4.0 2017-08-20 18:29:31 +03:00
Denis Demchenko
36db325c62 Fix browsers parser 2017-08-20 18:22:28 +03:00
Denis Demchenko
47c6614750 Export Bowser 2017-08-20 18:22:00 +03:00
Denis Demchenko
076ee810bd Setup acceptance tests with list of UAs 2017-08-20 18:21:17 +03:00
Denis Demchenko
99fde0a154 Add a new test for Parser and fix the names of existed ones 2017-08-19 19:55:41 +03:00
Denis Demchenko
7ea344e454 Fix the helper to convert tests to yml 2017-08-17 23:55:47 +03:00
Denis Demchenko
5c753edb75 Fix macOS version parsing 2017-08-17 23:55:21 +03:00
Denis Demchenko
b2aded435b Bump babel-preset-env version 2017-08-17 23:37:45 +03:00
Denis Demchenko
92ba6022c9 Add useragentstrings.yml 2017-08-17 23:37:24 +03:00
Denis Demchenko
663e769cdc Add a helper script to convert all the tests to yaml 2017-08-17 23:36:55 +03:00
Denis Demchenko
7db868cc29 Fix macOS version parser
Make it able to read all the numbers with dots
2017-08-17 23:35:40 +03:00
Denis Demchenko
6976da7da5 Make versions of browsers non-required properties 2017-08-17 23:33:46 +03:00
Denis Demchenko
efce17881f Fix iPhone and iPod detection 2017-06-09 23:49:08 +03:00
Denis Demchenko
45eec907e1 Ignore auto-generated lib folder 2017-06-09 23:04:58 +03:00
Denis Demchenko
a794b10797 Add an engines parser 2017-06-09 23:04:43 +03:00
Denis Demchenko
c3ad15e0ff Add more jsdoc for parsePlatform 2017-06-09 22:15:19 +03:00
Denis Demchenko
4fc00cc427 Add more details about parsed Amazon device 2017-06-09 22:08:48 +03:00
Denis Demchenko
3da8552f0f Define Galaxy Nexus as a mobile type 2017-06-09 21:59:34 +03:00
Denis Demchenko
bca14f50c8 Add description for parser-platforms 2017-06-09 21:58:44 +03:00
Denis Demchenko
a65540dc15 Add platform parser 2017-06-09 01:12:44 +03:00
Denis Demchenko
38320b1409 Change Bowser's constructor 2017-06-09 01:12:21 +03:00
Denis Demchenko
2c8f17b037 Add Linux detection 2017-06-08 23:35:08 +03:00
Denis Demchenko
d5a439f097 Fix Android detection 2017-06-08 23:32:11 +03:00
Denis Demchenko
39afeb5615 Replace OS version regexps by more greedy ones 2017-06-08 23:01:16 +03:00
Denis Demchenko
3cd9da66ae Add support of rendering engines 2017-06-08 22:34:58 +03:00
Denis Demchenko
0694b30fc6 Add testem as a main test runner 2017-06-08 22:23:27 +03:00
Denis Demchenko
19646053ce Complete Bowser's methods by call a Parser instance 2017-06-08 21:26:05 +03:00
Denis Demchenko
5a235015aa Add jsdoc descriptions for Parser's methods 2017-06-08 20:51:04 +03:00
Denis Demchenko
6b5974af2e Add more OS descriptors 2017-05-18 23:56:26 +03:00
Denis Demchenko
59fc2d639f Add Windows OS descriptor 2017-05-18 23:14:31 +03:00
Denis Demchenko
f5be32be3b Merge branch 'master' into v2 2017-05-18 23:01:05 +03:00
Denis Demchenko
8b37abf268 Change descriptors naming and add some information about them 2017-05-18 22:57:18 +03:00
Denis Demchenko
8808d5747b Add sinon to package deps 2017-04-15 22:52:59 +03:00
Denis Demchenko
b057077b68 Add OS parsing 2017-04-15 22:50:07 +03:00
Denis Demchenko
c50d0449d3 Add Parser#getBrowserName and Parser#getBrowserVersion 2017-04-09 22:46:23 +03:00
Denis Demchenko
b5aa54553f Add a spy to track calling Parser._parseBrowser when Parser.getBrowser called 2017-04-09 22:36:03 +03:00
Denis Demchenko
ce885847ce Fix version matching 2017-04-09 22:30:19 +03:00
Denis Demchenko
d57094d857 Finish Parser#_parseBrowser function 2017-04-09 22:09:47 +03:00
Denis Demchenko
9e46db26ed make public getBrowser and private parseBrowser 2017-04-09 19:16:38 +03:00
Denis Demchenko
3bb6654320 Continue writing 2017-04-09 17:13:00 +03:00
Denis Demchenko
575ba8076e fist commit 2017-04-04 23:03:47 +03:00
64 changed files with 30399 additions and 2715 deletions

20
.babelrc Normal file
View File

@ -0,0 +1,20 @@
{
"presets": [["@babel/preset-env", {
"useBuiltIns": "entry",
"modules": "cjs",
"loose": true,
"targets": {
"ie": "8",
"browsers": ">2%"
}
}]],
"plugins": [
"add-module-exports"
],
"env": {
"test": {
"plugins": [ "istanbul" ],
"presets": [["@babel/preset-env", { "targets": { "node": "current" } }]]
}
}
}

1
.coveralls.yml Normal file
View File

@ -0,0 +1 @@

View File

@ -3,6 +3,7 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[{*.js,*.md}]
charset = utf-8

14
.eslintrc.yml Normal file
View File

@ -0,0 +1,14 @@
parser: babel-eslint
extends: airbnb-base
rules:
no-underscore-dangle: 0
no-void: 0
import/extensions:
- 'error'
- 'ignorePackages'
- {js: 'always'}
import/prefer-default-export: 1
plugins:
- ava
- import

42
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,42 @@
# 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 ❤️
## 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 Browser Support and 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. Also, make sure to keep the list of browser aliases up-to-date in `src/constants.js`.
For creating aliases, keep the following guidelines in mind:
- use only lowercase letters for names
- replace special characters such as space and dashes by underscore
- whenever possible drop the word `browser` from the original browser name
- always check for possible duplicates
- aliases are supposed to also be a shorter version of the original name
Examples:
`Opera Coast` --> `opera_coast`
`UC Browser` --> `uc`
`SeaMonkey` --> `seamonkey`
## 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
```

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: lancedikson
open_collective: lancedikson

View File

@ -1,5 +1,5 @@
Template to report about browser detection issue
`window.navigator.userAgent` of the browser is: ...
And it's detected like a ...
But real name of the browser is ...
And it's detected like ...
However, the real name of the browser is ...

19
.github/release-drafter.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name-template: 'v$RESOLVED_VERSION 🌈'
tag-template: 'v$RESOLVED_VERSION'
version-resolver:
major:
labels:
- major
minor:
labels:
- minor
patch:
labels:
- patch
default: patch
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
template: |
## Changes
$CHANGES

View File

@ -0,0 +1,20 @@
name: 📝 Draft or update next release
concurrency: draft_or_update_next_release
on:
push:
branches:
- main
workflow_dispatch:
jobs:
prepare-deployment:
name: 📝 Draft or update next release
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v1
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

38
.github/workflows/merge-to-master.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: 'Merge to master'
on:
push:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.16.3]
steps:
- name: Get branch name (merge)
if: github.event_name != 'pull_request'
shell: bash
run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | tr / -)" >> $GITHUB_ENV
- name: Get branch name (pull request)
if: github.event_name == 'pull_request'
shell: bash
run: echo "BRANCH_NAME=$(echo ${GITHUB_HEAD_REF} | tr / -)" >> $GITHUB_ENV
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm i -g nyc
- run: npm ci
- run: npm run build
- run: nyc npm test && nyc report --reporter=text-lcov | ./node_modules/coveralls/bin/coveralls.js
env:
COVERALLS_SERVICE_NAME: GithubActions
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
COVERALLS_GIT_BRANCH: ${{ env.BRANCH_NAME }}

29
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Release
on:
# This job runs when a new release is published
release:
types: [published]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16
registry-url: https://registry.npmjs.org
- uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
# Store the name of the release
# See https://stackoverflow.com/questions/58177786/get-the-current-pushed-tag-in-github-actions
- run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- run: npm ci
- run: npm version $RELEASE_VERSION --no-git-tag-version
- run: npm run build
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.BOWSER_NPM_PUBLISH_TOKEN }}

44
.github/workflows/pull-request.yml vendored Normal file
View File

@ -0,0 +1,44 @@
name: 'Pull Request'
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [12.16.3]
name: Node ${{ matrix.node }}
steps:
- name: 'Checkout latest code'
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up node
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run tests
run: npm run test
lint:
name: 'ESLint'
runs-on: ubuntu-latest
steps:
- name: Checkout latest code
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up node
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint:check

7
.gitignore vendored
View File

@ -1,4 +1,7 @@
node_modules/
.idea/
/bowser.js
/bowser.min.js
.nyc_output
coverage
dist
bundled.js*
es5.js*

View File

@ -1,3 +1,10 @@
make
src/useragents.js
Makefile
test
.nyc_output
coverage
**/.*
node_modules
.github
docs
*.gz
jsdoc.json
webpack.config.js

1
.npmrc Normal file
View File

@ -0,0 +1 @@
registry=https://registry.npmjs.org

10
.nycrc Normal file
View File

@ -0,0 +1,10 @@
{
"sourceMap": false,
"instrument": false,
"include": [
"src/**/*.js"
],
"exclude": [
"*.js"
]
}

14
.testem.json Normal file
View File

@ -0,0 +1,14 @@
{
"framework": "custom",
"src_files": [
"src/**/*.js",
"test/**/*.js"
],
"launchers": {
"tap": {
"command": "ava test/**/*.js --tap",
"protocol": "tap"
}
},
"launch_in_dev": [ "tap" ]
}

View File

@ -1,8 +0,0 @@
language: node_js
node_js:
- "4.4.7"
notifications:
email:
- dustin@dustindiaz.com
script: NODE_ENV=test ./node_modules/.bin/mocha --reporter spec

View File

@ -1,5 +1,147 @@
# Bowser Changelog
### 2.11.0 (Sep 12, 2020)
- [ADD] Added support for aliases in `Parser#is` method (#437)
- [ADD] Added more typings (#438, #427)
- [ADD] Added support for MIUI Browser (#436)
### 2.10.0 (Jul 9, 2020)
- [FIX] Fix for Firefox detection on iOS 13 [#415]
- [FIX] Fixes for typings.d.ts [#409]
- [FIX] Updated development dependencies
### 2.9.0 (Jan 28, 2020)
- [ADD] Export more methods and constants via .d.ts [#388], [#390]
### 2.8.1 (Dec 26, 2019)
- [FIX] Reverted [#382] as it broke build
### 2.8.0 (Dec 26, 2019)
- [ADD] Add polyfills for Array.find & Object.assign [#383]
- [ADD] Export constants with types.d.ts [#382]
- [FIX] Add support for WeChat on Windows [#381]
- [FIX] Fix detection of Firefox on iPad [#379]
- [FIX] Add detection of Electron [#375]
- [FIX] Updated dev-dependencies
### 2.7.0 (Oct 2, 2019)
- [FIX] Add support for QQ Browser [#362]
- [FIX] Add support for GSA [#364]
- [FIX] Updated dependencies
### 2.6.0 (Sep 6, 2019)
- [ADD] Define "module" export in package.json [#354]
- [FIX] Fix Tablet PC detection [#334]
### 2.5.4 (Sep 2, 2019)
- [FIX] Exclude docs from the npm package [#349]
### 2.5.3 (Aug 4, 2019)
- [FIX] Add MacOS names support [#338]
- [FIX] Point typings.d.ts from package.json [#341]
- [FIX] Upgrade dependencies
### 2.5.2 (July 17, 2019)
- [FIX] Fixes the bug undefined method because of failed build (#335)
### 2.5.1 (July 17, 2019)
- [FIX] Fixes the bug with a custom Error class (#335)
- [FIX] Fixes the settings for Babel to reduce the bundle size (#259)
### 2.5.0 (July 16, 2019)
- [ADD] Add constant output so that users can quickly get all types (#325)
- [FIX] Add support for Roku OS (#332)
- [FIX] Update devDependencies
- [FIX] Fix docs, README and added funding information
### 2.4.0 (May 3, 2019)
- [FIX] Update regexp for generic browsers (#310)
- [FIX] Fix issues with module.exports (#318)
- [FIX] Update devDependencies (#316, #321, #322)
- [FIX] Fix docs (#320)
### 2.3.0 (April 14, 2019)
- [ADD] Add support for Blink-based MS Edge (#311)
- [ADD] Add more types for TS (#289)
- [FIX] Update dev-dependencies
- [FIX] Update docs
### 2.2.1 (April 12, 2019)
- [ADD] Add an alias for Samsung Internet
- [FIX] Fix browser name detection for browsers without an alias (#313)
### 2.2.0 (April 7, 2019)
- [ADD] Add short aliases for browser names (#295)
- [FIX] Fix Yandex Browser version detection (#308)
### 2.1.2 (March 6, 2019)
- [FIX] Fix buggy `getFirstMatch` reference
### 2.1.1 (March 6, 2019)
- [ADD] Add detection of PlayStation 4 (#291)
- [ADD] Deploy docs on GH Pages (#293)
- [FIX] Fix files extensions for importing (#294)
- [FIX] Fix docs (#295)
### 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)
- [ADD] Add a typings file (#277)
- [ADD] Added support for Googlebot recognition (#278)
- [FIX] Update building tools, avoid security issues
### 2.0.0-beta.3 (September 15, 2018)
- [FIX] Fix Chrome Mobile detection (#253)
- [FIX] Use built bowser for CI (#252)
- [FIX] Update babel-plugin-add-module-exports (#251)
### 2.0.0-beta.2 (September 9, 2018)
- [FIX] Fix failing comparing version through `Parser.satisfies` (#243)
- [FIX] Fix travis testing, include eslint into CI testing
- [FIX] Add support for Maxthon desktop browser (#246)
- [FIX] Add support for Swing browser (#248)
- [DOCS] Regenerate docs
### 2.0.0-beta.1 (August 18, 2018)
- [ADD] Add loose version comparison to `Parser.compareVersion()` and `Parser.satisfies()`
- [CHORE] Add CONTRIBUTING.md
- [DOCS] Regenerate docs
### 2.0.0-alpha.4 (August 2, 2018)
- [DOCS] Fix usage docs (#238)
- [CHANGE] Make `./es5.js` the main file of the package (#239)
### 2.0.0-alpha.3 (July 22, 2018)
- [CHANGE] Rename split and rename `compiled.js` to `es5.js` and `bundled.js` (#231, #236, #237)
- [ADD] Add `Parser.some` (#235)
### 2.0.0-alpha.2 (July 17, 2018)
- [CHANGE] Make `src/bowser` main file instead of the bundled one
- [CHANGE] Move the bundled file to the root of the package to make it possible to `require('bowser/compiled')` (#231)
- [REMOVE] Remove `typings.d.ts` before stable release (#232)
- [FIX] Improve Nexus devices detection (#233)
### 2.0.0-alpha.1 (July 9, 2018)
- [ADD] `Bowser.getParser()`
- [ADD] `Bowser.parse`
- [ADD] `Parser` class which describes parsing process
- [CHANGE] Change bowser's returning object
- [REMOVE] Remove bower support
### 1.9.4 (June 28, 2018)
- [FIX] Fix NAVER Whale browser detection (#220)
- [FIX] Fix MZ Browser browser detection (#219)
- [FIX] Fix Firefox Focus browser detection (#191)
- [FIX] Fix webOS browser detection (#186)
### 1.9.3 (March 12, 2018)
- [FIX] Fix `typings.d.ts` — add `ipad`, `iphone`, `ipod` flags to the interface
### 1.9.2 (February 5, 2018)
- [FIX] Fix `typings.d.ts` — add `osname` flag to the interface
@ -35,7 +177,7 @@
### 1.5.0 (October 31, 2016)
- [ADD] Throw an error when `minVersion` map has not a string as a version and fix readme (#165)
- [FIX] Fix truly detection of Windows Phones (#167)
- [FIX] Fix truly detection of Windows Phones (#167)
### 1.4.6 (September 19, 2016)
- [FIX] Fix mobile Opera's version detection on Android
@ -73,4 +215,4 @@
- [FEATURE] Add `bowser.check` method
- [DOC] Changelog started
- [DOC] Add API section to README
- [FIX] Fix detection of browser type (A/C/X) for Chromium
- [FIX] Fix detection of browser type (A/C/X) for Chromium

View File

@ -1,16 +0,0 @@
boosh:
node make/build.js
REPORTER = spec
test:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER) \
test-w:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER) \
--growl \
--watch
.PHONY: test test-w

331
README.md
View File

@ -1,210 +1,177 @@
## Bowser
A Browser detector. Because sometimes, there is no other way, and not even good modern browsers always provide good feature detection mechanisms.
A small, fast and rich-API browser/platform/engine detector for both browser and node.
- **Small.** Use plain ES5-version which is ~4.8kB gzipped.
- **Optimized.** Use only those parsers you need — it doesn't do useless work.
- **Multi-platform.** It's browser- and node-ready, so you can use it in any environment.
[![Build Status](https://travis-ci.org/lancedikson/bowser.svg?branch=master)](https://travis-ci.org/lancedikson/bowser)
Don't hesitate to support the project on Github or [OpenCollective](https://opencollective.com/bowser) if you like it ❤️ Also, contributors are always welcome!
So... it works like this:
[![Financial Contributors on Open Collective](https://opencollective.com/bowser/all/badge.svg?label=financial+contributors)](https://opencollective.com/bowser) [![Build Status](https://travis-ci.org/lancedikson/bowser.svg?branch=master)](https://travis-ci.org/lancedikson/bowser/) [![Greenkeeper badge](https://badges.greenkeeper.io/lancedikson/bowser.svg)](https://greenkeeper.io/) [![Coverage Status](https://coveralls.io/repos/github/lancedikson/bowser/badge.svg?branch=master)](https://coveralls.io/github/lancedikson/bowser?branch=master) ![Downloads](https://img.shields.io/npm/dm/bowser)
``` js
if (bowser.msie && bowser.version <= 6) {
alert('Hello China');
# Contents
- [Overview](#overview)
- [Use cases](#use-cases)
# Overview
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. Check it out on this page: https://bowser-js.github.io/bowser-online/.
### ⚠️ Version 2.0 breaking changes ⚠️
Version 2.0 has drastically changed the API. All available methods are on the [docs page](https://bowser-js.github.io/bowser/docs/).
_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, ES6, and CommonJS module systems.
```javascript
const Bowser = require("bowser"); // CommonJS
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.
In case you don't use your own `babel-polyfill` you may need to have pre-built bundle with all needed polyfills.
So, for you it's suitable to require bowser like this: `require('bowser/bundled')`.
As the result, you get a ES5 version of bowser with `babel-polyfill` bundled together.
You may need to use the source files, so they will be available in the package as well.
## Browser props detection
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);
console.log(`The current browser name is "${browser.getBrowserName()}"`);
// The current browser name is "Internet Explorer"
```
or
```javascript
const browser = Bowser.getParser(window.navigator.userAgent);
console.log(browser.getBrowser());
// outputs
{
name: "Internet Explorer"
version: "11.0"
}
```
## 1.1.0 breaking changes
We don't save built script in the repo anymore. The main file (`src/bowser.js`) is available through NPM or Bower.
Also you can download minified file from [the release page](https://github.com/ded/bowser/releases).
or
## 1.0.0 breaking changes
`browser = require('bowser').browser;` becomes `bowser = require('bowser');`
```javascript
console.log(Bowser.parse(window.navigator.userAgent));
---
## API
### bowser`:Object`
Use it to get object with detected flags of your current browser.
### bowser._detect(ua `:String`)`:Object`
Use it to get object with detected flags from User Agent string.
### bowser.check(minVersions`:Object`, strictMode`:Boolean`, [ua]`:String`)`:Boolean`
Use it to check if browser is supported. In default non-strict mode any browser family not present in `minVersions` will pass the check (like Chrome in the third call in the sample bellow). When strict mode is enabled then any not specified browser family in `minVersions` will cause `check` to return `false` (in the sample it is the fourth call, the last one).
``` js
/**
* in case of using IE10
*/
bowser.check({msie: "11"}); // true
bowser.check({msie: "9.0"}); // false
/**
* specific user agent
*/
bowser.check({chrome: "45"}, window.navigator.userAgent); // true
/**
* but false in strict mode
*/
bowser.check({chrome: "45"}, true, window.navigator.userAgent); // false
```
### bowser.compareVersions(versions`:Array<String>`)`:Number`
Use it to compare two versions.
``` js
bowser.compareVersions(['9.0', '10']);
// -1
```
### bowser.isUnsupportedBrowser(minVersions`:Object`, [strictMode]`:Boolean`, [ua]`:string`)`:Boolean`
Use it to check if browser is unsupported.
``` js
bowser.isUnsupportedBrowser({msie: "10"}, window.navigator.userAgent);
// true / false
```
See more examples in [tests](test/test.js).
---
## Bowser Flags
Your mileage may vary, but these flags should be set. See Contributing below.
``` js
alert('Hello ' + bowser.name + ' ' + bowser.version);
```
### All detected browsers
These flags are set for all detected browsers:
* `name` - A human readable name for this browser. E.g. 'Chrome', ''
* `version` - Version number for the browser. E.g. '32.0'
For unknown browsers, Bowser makes a best guess from the UA string. So, these may not be set.
### Rendering engine flags
If detected, one of these flags may be set to true:
* `webkit` - Chrome 0-27, Android <4.4, iOs, BB, etc.
* `blink` - Chrome >=28, Android >=4.4, Opera, etc.
* `gecko` - Firefox, etc.
* `msie` - IE <= 11
* `msedge` - IE > 11
Safari, Chrome and some other minor browsers will report that they have `webkit` engines.
Firefox and Seamonkey will report that they have `gecko` engines.
``` js
if (bowser.webkit) {
// do stuff with safari & chrome & opera & android & blackberry & webos & silk
// outputs
{
browser: {
name: "Internet Explorer"
version: "11.0"
},
os: {
name: "Windows"
version: "NT 6.3"
versionName: "8.1"
},
platform: {
type: "desktop"
},
engine: {
name: "Trident"
version: "7.0"
}
}
```
### Device flags
If detected, one of these flags may be set to true:
* `mobile` - All detected mobile OSes are additionally flagged `mobile`, **unless it's a tablet**
* `tablet` - If a tablet device is detected, the flag `tablet` is **set instead of `mobile`**.
## Filtering browsers
### Browser flags
If detected, one of these flags may be set to true. The rendering engine flag is shown in []'s:
You could want to filter some particular browsers to provide any special support for them or make any workarounds.
It could look like this:
* `chrome` - [`webkit`|`blink`]
* `chromium` - [`webkit`|`blink`]
* `firefox` - [`gecko`]
* `msie`
* `msedge`
* `safari` - [`webkit`]
* `android` - native browser - [`webkit`|`blink`]
* `ios` - native browser - [`webkit`]
* `opera` - [`blink` if >=15]
* `samsungBrowser` - [`blink`]
* `phantom` - [`webkit`]
* `blackberry` - native browser - [`webkit`]
* `webos` - native browser - [`webkit`]
* `silk` - Amazon Kindle browser - [`webkit`]
* `bada` - [`webkit`]
* `tizen` - [`webkit`]
* `seamonkey` - [`gecko`]
* `sailfish` - [`gecko`]
* `ucbrowser` — [`webkit`]
* `qupzilla` — [`webkit`]
* `vivaldi` — [`blink`]
* `sleipnir` — [`blink`]
* `kMeleon` — [`gecko`]
```javascript
const browser = Bowser.getParser(window.navigator.userAgent);
const isValidBrowser = browser.satisfies({
// declare browsers per OS
windows: {
"internet explorer": ">10",
},
macos: {
safari: ">10.1"
},
For all detected browsers the browser version is set in the `version` field.
// per platform (mobile, desktop or tablet)
mobile: {
safari: '>=9',
'android browser': '>3.10'
},
### OS Flags
If detected, one of these flags may be set to true:
// or in general
chrome: "~20.1.1432",
firefox: ">31",
opera: ">=22",
* `mac`
* `windows` - other than Windows Phone
* `windowsphone`
* `linux` - other than `android`, `chromeos`, `webos`, `tizen`, and `sailfish`
* `chromeos`
* `android`
* `ios` - also sets one of `iphone`/`ipad`/`ipod`
* `blackberry`
* `firefoxos`
* `webos` - may also set `touchpad`
* `bada`
* `tizen`
* `sailfish`
// also supports equality operator
chrome: "=20.1.1432", // will match particular build only
`osname` and `osversion` may also be set:
* `osname` - for the OS flags detected above: macOS, Windows, Windows Phone, Linux, Chrome OS, Android, iOS, Blackberry OS, Firefox OS, WebOS, Bada, Tizen, Sailfish OS, and Xbox
* `osversion` - for Android, iOS, MacOS, Windows, Windows Phone, WebOS, Bada, and Tizen. If included in UA string.
iOS is always reported as `ios` and additionally as `iphone`/`ipad`/`ipod`, whichever one matches best.
If WebOS device is an HP TouchPad the flag `touchpad` is additionally set.
### Browser capability grading
One of these flags may be set:
* `a` - This browser has full capabilities
* `c` - This browser has degraded capabilities. Serve simpler version
* `x` - This browser has minimal capabilities and is probably not well detected.
There is no `b`. For unknown browsers, none of these flags may be set.
### Ender Support
`package.json`
``` json
"dependencies": {
"bowser": "x.x.x"
}
// and loose-equality operator
chrome: "~20", // will match any 20.* sub-version
chrome: "~20.1" // will match any 20.1.* sub-version (20.1.19 as well as 20.1.12.42-alpha.1)
});
```
``` js
if (require('bowser').chrome) {
alert('Hello Silicon Valley')
}
```
Settings for any particular OS or platform has more priority and redefines settings of standalone browsers.
Thus, you can define OS or platform specific rules and they will have more priority in the end.
### Contributing
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):
More of API and possibilities you will find in the `docs` folder.
``` sh
$ npm install
$ make test
```
### Browser names for `.satisfies()`
Please do not check-in the built files `bowser.js` and `bowser.min.js` in pull requests.
By default you are supposed to use the full browser name for `.satisfies`.
But, there's a short way to define a browser using short aliases. The full
list of aliases can be found in [the file](src/constants.js).
### Adding tests
See the list in `src/useragents.js` 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
## Similar Projects
* [Kong](https://github.com/BigBadBleuCheese/Kong) - A C# port of Bowser.
### License
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](.github/CONTRIBUTING.md)].
<a href="https://github.com/lancedikson/bowser/graphs/contributors"><img src="https://opencollective.com/bowser/contributors.svg?width=890&button=false" /></a>
### Financial Contributors
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/bowser/contribute)]
#### Individuals
<a href="https://opencollective.com/bowser"><img src="https://opencollective.com/bowser/individuals.svg?width=890"></a>
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/bowser/contribute)]
<a href="https://opencollective.com/bowser/organization/0/website"><img src="https://opencollective.com/bowser/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/1/website"><img src="https://opencollective.com/bowser/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/2/website"><img src="https://opencollective.com/bowser/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/3/website"><img src="https://opencollective.com/bowser/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/4/website"><img src="https://opencollective.com/bowser/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/5/website"><img src="https://opencollective.com/bowser/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/6/website"><img src="https://opencollective.com/bowser/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/7/website"><img src="https://opencollective.com/bowser/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/8/website"><img src="https://opencollective.com/bowser/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/9/website"><img src="https://opencollective.com/bowser/organization/9/avatar.svg"></a>
## License
Licensed as MIT. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.

View File

@ -1,33 +0,0 @@
{
"name": "bowser",
"description": "Lightweight browser detector",
"keywords": [
"browser",
"useragent",
"user-agent",
"parser",
"ua",
"detection",
"ender",
"sniff"
],
"version": "1.9.2",
"homepage": "https://github.com/lancedikson/bowser",
"scripts": [
"src/bowser.js"
],
"authors": [
"Dustin Diaz <dustin@dustindiaz.com> (http://dustindiaz.com)",
"Denis Demchenko <lance@dikson.me>"
],
"moduleType": [],
"license": "MIT",
"main": "src/bowser.js",
"ignore": [
"node_modules",
"test",
"make",
"**/.*",
"Makefile"
]
}

505
docs/Bowser.html Normal file
View File

@ -0,0 +1,505 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bowser - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Bowser.html">Bowser</a><ul class='methods'><li data-type='method'><a href="Bowser.html#.getParser">getParser</a></li><li data-type='method'><a href="Bowser.html#.parse">parse</a></li></ul></li><li><a href="Parser.html">Parser</a><ul class='methods'><li data-type='method'><a href="Parser.html#getBrowser">getBrowser</a></li><li data-type='method'><a href="Parser.html#getBrowserName">getBrowserName</a></li><li data-type='method'><a href="Parser.html#getBrowserVersion">getBrowserVersion</a></li><li data-type='method'><a href="Parser.html#getEngine">getEngine</a></li><li data-type='method'><a href="Parser.html#getEngineName">getEngineName</a></li><li data-type='method'><a href="Parser.html#getOS">getOS</a></li><li data-type='method'><a href="Parser.html#getOSName">getOSName</a></li><li data-type='method'><a href="Parser.html#getOSVersion">getOSVersion</a></li><li data-type='method'><a href="Parser.html#getPlatform">getPlatform</a></li><li data-type='method'><a href="Parser.html#getPlatformType">getPlatformType</a></li><li data-type='method'><a href="Parser.html#getResult">getResult</a></li><li data-type='method'><a href="Parser.html#getUA">getUA</a></li><li data-type='method'><a href="Parser.html#is">is</a></li><li data-type='method'><a href="Parser.html#isBrowser">isBrowser</a></li><li data-type='method'><a href="Parser.html#parse">parse</a></li><li data-type='method'><a href="Parser.html#parseBrowser">parseBrowser</a></li><li data-type='method'><a href="Parser.html#parseEngine">parseEngine</a></li><li data-type='method'><a href="Parser.html#parseOS">parseOS</a></li><li data-type='method'><a href="Parser.html#parsePlatform">parsePlatform</a></li><li data-type='method'><a href="Parser.html#satisfies">satisfies</a></li><li data-type='method'><a href="Parser.html#some">some</a></li><li data-type='method'><a href="Parser.html#test">test</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#assign">assign</a></li><li><a href="global.html#find">find</a></li><li><a href="global.html#getAndroidVersionName">getAndroidVersionName</a></li><li><a href="global.html#getBrowserAlias">getBrowserAlias</a></li><li><a href="global.html#getBrowserTypeByAlias">getBrowserTypeByAlias</a></li><li><a href="global.html#getFirstMatch">getFirstMatch</a></li><li><a href="global.html#getMacOSVersionName">getMacOSVersionName</a></li><li><a href="global.html#getSecondMatch">getSecondMatch</a></li><li><a href="global.html#getVersionPrecision">getVersionPrecision</a></li><li><a href="global.html#map">map</a></li><li><a href="global.html#matchAndReturnConst">matchAndReturnConst</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">Bowser</h1>
<section>
<header>
<h2>
Bowser
</h2>
<div class="class-description"><p>Bowser is a static object, that provides an API to the Parsers</p></div>
</header>
<article>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id=".getParser"><span class="type-signature">(static) </span>getParser<span class="signature">(UA, skipParsing<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {<a href="Parser.html">Parser</a>}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="bowser.js.html">bowser.js</a>, <a href="bowser.js.html#line40">line 40</a>
</li></ul></dd>
</dl>
<div class="description">
<p>Creates a <a href="Parser.html">Parser</a> instance</p>
</div>
<h5>Example</h5>
<pre class="prettyprint"><code>const parser = Bowser.getParser(window.navigator.userAgent);
const result = parser.getResult();</code></pre>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>UA</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="attributes">
</td>
<td class="default">
</td>
<td class="description last"><p>UserAgent string</p></td>
</tr>
<tr>
<td class="name"><code>skipParsing</code></td>
<td class="type">
<span class="param-type">Boolean</span>
</td>
<td class="attributes">
&lt;optional><br>
</td>
<td class="default">
<code>false</code>
</td>
<td class="description last"><p>Will make the Parser postpone parsing until you ask it
explicitly. Same as <code>skipParsing</code> for <a href="Parser.html">Parser</a>.</p></td>
</tr>
</tbody>
</table>
<h5>Throws:</h5>
<dl>
<dt>
<div class="param-desc">
<p>when UA is not a String</p>
</div>
</dt>
<dd></dd>
<dt>
<dl class="param-type">
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
<h5>Returns:</h5>
<dl class="param-type">
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="Parser.html">Parser</a></span>
</dd>
</dl>
<h4 class="name" id=".parse"><span class="type-signature">(static) </span>parse<span class="signature">(UA)</span><span class="type-signature"> &rarr; {<a href="global.html#ParsedResult">ParsedResult</a>}</span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="bowser.js.html">bowser.js</a>, <a href="bowser.js.html#line56">line 56</a>
</li></ul></dd>
</dl>
<div class="description">
<p>Creates a <a href="Parser.html">Parser</a> instance and runs Parser.getResult immediately</p>
</div>
<h5>Example</h5>
<pre class="prettyprint"><code>const result = Bowser.parse(window.navigator.userAgent);</code></pre>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>UA</code></td>
<td class="type">
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<h5>Returns:</h5>
<dl class="param-type">
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="global.html#ParsedResult">ParsedResult</a></span>
</dd>
</dl>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Sat Sep 12 2020 11:21:13 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>

View File

@ -0,0 +1,234 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>BowserUAIsNotAStringError - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Bowser.html">Bowser</a><ul class='methods'><li data-type='method'><a href="Bowser.html#.getParser">getParser</a></li><li data-type='method'><a href="Bowser.html#.parse">parse</a></li></ul></li><li><a href="BowserUAIsNotAStringError.html">BowserUAIsNotAStringError</a></li><li><a href="Parser.html">Parser</a><ul class='methods'><li data-type='method'><a href="Parser.html#getBrowser">getBrowser</a></li><li data-type='method'><a href="Parser.html#getBrowserName">getBrowserName</a></li><li data-type='method'><a href="Parser.html#getBrowserVersion">getBrowserVersion</a></li><li data-type='method'><a href="Parser.html#getEngine">getEngine</a></li><li data-type='method'><a href="Parser.html#getEngineName">getEngineName</a></li><li data-type='method'><a href="Parser.html#getOS">getOS</a></li><li data-type='method'><a href="Parser.html#getOSName">getOSName</a></li><li data-type='method'><a href="Parser.html#getOSVersion">getOSVersion</a></li><li data-type='method'><a href="Parser.html#getPlatform">getPlatform</a></li><li data-type='method'><a href="Parser.html#getPlatformType">getPlatformType</a></li><li data-type='method'><a href="Parser.html#getResult">getResult</a></li><li data-type='method'><a href="Parser.html#getUA">getUA</a></li><li data-type='method'><a href="Parser.html#is">is</a></li><li data-type='method'><a href="Parser.html#isBrowser">isBrowser</a></li><li data-type='method'><a href="Parser.html#parse">parse</a></li><li data-type='method'><a href="Parser.html#parseBrowser">parseBrowser</a></li><li data-type='method'><a href="Parser.html#parseEngine">parseEngine</a></li><li data-type='method'><a href="Parser.html#parseOS">parseOS</a></li><li data-type='method'><a href="Parser.html#parsePlatform">parsePlatform</a></li><li data-type='method'><a href="Parser.html#satisfies">satisfies</a></li><li data-type='method'><a href="Parser.html#some">some</a></li><li data-type='method'><a href="Parser.html#test">test</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#getAndroidVersionName">getAndroidVersionName</a></li><li><a href="global.html#getBrowserAlias">getBrowserAlias</a></li><li><a href="global.html#getBrowserTypeByAlias">getBrowserTypeByAlias</a></li><li><a href="global.html#getFirstMatch">getFirstMatch</a></li><li><a href="global.html#getSecondMatch">getSecondMatch</a></li><li><a href="global.html#getVersionPrecision">getVersionPrecision</a></li><li><a href="global.html#map">map</a></li><li><a href="global.html#matchAndReturnConst">matchAndReturnConst</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">BowserUAIsNotAStringError</h1>
<section>
<header>
<h2>
BowserUAIsNotAStringError
</h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="BowserUAIsNotAStringError"><span class="type-signature"></span>new BowserUAIsNotAStringError<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="bowser.js.html">bowser.js</a>, <a href="bowser.js.html#line20">line 20</a>
</li></ul></dd>
</dl>
<h5 class="subsection-title">Properties:</h5>
<table class="props">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>name</code></td>
<td class="type">
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
</div>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Tue Jul 16 2019 22:20:27 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>

3142
docs/Parser.html Normal file

File diff suppressed because it is too large Load Diff

146
docs/bowser.js.html Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>bowser.js - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Bowser.html">Bowser</a><ul class='methods'><li data-type='method'><a href="Bowser.html#.getParser">getParser</a></li><li data-type='method'><a href="Bowser.html#.parse">parse</a></li></ul></li><li><a href="Parser.html">Parser</a><ul class='methods'><li data-type='method'><a href="Parser.html#getBrowser">getBrowser</a></li><li data-type='method'><a href="Parser.html#getBrowserName">getBrowserName</a></li><li data-type='method'><a href="Parser.html#getBrowserVersion">getBrowserVersion</a></li><li data-type='method'><a href="Parser.html#getEngine">getEngine</a></li><li data-type='method'><a href="Parser.html#getEngineName">getEngineName</a></li><li data-type='method'><a href="Parser.html#getOS">getOS</a></li><li data-type='method'><a href="Parser.html#getOSName">getOSName</a></li><li data-type='method'><a href="Parser.html#getOSVersion">getOSVersion</a></li><li data-type='method'><a href="Parser.html#getPlatform">getPlatform</a></li><li data-type='method'><a href="Parser.html#getPlatformType">getPlatformType</a></li><li data-type='method'><a href="Parser.html#getResult">getResult</a></li><li data-type='method'><a href="Parser.html#getUA">getUA</a></li><li data-type='method'><a href="Parser.html#is">is</a></li><li data-type='method'><a href="Parser.html#isBrowser">isBrowser</a></li><li data-type='method'><a href="Parser.html#parse">parse</a></li><li data-type='method'><a href="Parser.html#parseBrowser">parseBrowser</a></li><li data-type='method'><a href="Parser.html#parseEngine">parseEngine</a></li><li data-type='method'><a href="Parser.html#parseOS">parseOS</a></li><li data-type='method'><a href="Parser.html#parsePlatform">parsePlatform</a></li><li data-type='method'><a href="Parser.html#satisfies">satisfies</a></li><li data-type='method'><a href="Parser.html#some">some</a></li><li data-type='method'><a href="Parser.html#test">test</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#assign">assign</a></li><li><a href="global.html#find">find</a></li><li><a href="global.html#getAndroidVersionName">getAndroidVersionName</a></li><li><a href="global.html#getBrowserAlias">getBrowserAlias</a></li><li><a href="global.html#getBrowserTypeByAlias">getBrowserTypeByAlias</a></li><li><a href="global.html#getFirstMatch">getFirstMatch</a></li><li><a href="global.html#getMacOSVersionName">getMacOSVersionName</a></li><li><a href="global.html#getSecondMatch">getSecondMatch</a></li><li><a href="global.html#getVersionPrecision">getVersionPrecision</a></li><li><a href="global.html#map">map</a></li><li><a href="global.html#matchAndReturnConst">matchAndReturnConst</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">bowser.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/*!
* Bowser - a browser detector
* https://github.com/lancedikson/bowser
* MIT License | (c) Dustin Diaz 2012-2015
* MIT License | (c) Denis Demchenko 2015-2019
*/
import Parser from './parser.js';
import {
BROWSER_MAP,
ENGINE_MAP,
OS_MAP,
PLATFORMS_MAP,
} from './constants.js';
/**
* Bowser class.
* Keep it simple as much as it can be.
* It's supposed to work with collections of {@link Parser} instances
* rather then solve one-instance problems.
* All the one-instance stuff is located in Parser class.
*
* @class
* @classdesc Bowser is a static object, that provides an API to the Parsers
* @hideconstructor
*/
class Bowser {
/**
* Creates a {@link Parser} instance
*
* @param {String} UA UserAgent string
* @param {Boolean} [skipParsing=false] Will make the Parser postpone parsing until you ask it
* explicitly. Same as `skipParsing` for {@link Parser}.
* @returns {Parser}
* @throws {Error} when UA is not a String
*
* @example
* const parser = Bowser.getParser(window.navigator.userAgent);
* const result = parser.getResult();
*/
static getParser(UA, skipParsing = false) {
if (typeof UA !== 'string') {
throw new Error('UserAgent should be a string');
}
return new Parser(UA, skipParsing);
}
/**
* Creates a {@link Parser} instance and runs {@link Parser.getResult} immediately
*
* @param UA
* @return {ParsedResult}
*
* @example
* const result = Bowser.parse(window.navigator.userAgent);
*/
static parse(UA) {
return (new Parser(UA)).getResult();
}
static get BROWSER_MAP() {
return BROWSER_MAP;
}
static get ENGINE_MAP() {
return ENGINE_MAP;
}
static get OS_MAP() {
return OS_MAP;
}
static get PLATFORMS_MAP() {
return PLATFORMS_MAP;
}
}
export default Bowser;
</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Sat Sep 12 2020 11:21:13 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>

2719
docs/global.html Normal file

File diff suppressed because it is too large Load Diff

223
docs/index.html Normal file
View File

@ -0,0 +1,223 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Bowser.html">Bowser</a><ul class='methods'><li data-type='method'><a href="Bowser.html#.getParser">getParser</a></li><li data-type='method'><a href="Bowser.html#.parse">parse</a></li></ul></li><li><a href="Parser.html">Parser</a><ul class='methods'><li data-type='method'><a href="Parser.html#getBrowser">getBrowser</a></li><li data-type='method'><a href="Parser.html#getBrowserName">getBrowserName</a></li><li data-type='method'><a href="Parser.html#getBrowserVersion">getBrowserVersion</a></li><li data-type='method'><a href="Parser.html#getEngine">getEngine</a></li><li data-type='method'><a href="Parser.html#getEngineName">getEngineName</a></li><li data-type='method'><a href="Parser.html#getOS">getOS</a></li><li data-type='method'><a href="Parser.html#getOSName">getOSName</a></li><li data-type='method'><a href="Parser.html#getOSVersion">getOSVersion</a></li><li data-type='method'><a href="Parser.html#getPlatform">getPlatform</a></li><li data-type='method'><a href="Parser.html#getPlatformType">getPlatformType</a></li><li data-type='method'><a href="Parser.html#getResult">getResult</a></li><li data-type='method'><a href="Parser.html#getUA">getUA</a></li><li data-type='method'><a href="Parser.html#is">is</a></li><li data-type='method'><a href="Parser.html#isBrowser">isBrowser</a></li><li data-type='method'><a href="Parser.html#parse">parse</a></li><li data-type='method'><a href="Parser.html#parseBrowser">parseBrowser</a></li><li data-type='method'><a href="Parser.html#parseEngine">parseEngine</a></li><li data-type='method'><a href="Parser.html#parseOS">parseOS</a></li><li data-type='method'><a href="Parser.html#parsePlatform">parsePlatform</a></li><li data-type='method'><a href="Parser.html#satisfies">satisfies</a></li><li data-type='method'><a href="Parser.html#some">some</a></li><li data-type='method'><a href="Parser.html#test">test</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#assign">assign</a></li><li><a href="global.html#find">find</a></li><li><a href="global.html#getAndroidVersionName">getAndroidVersionName</a></li><li><a href="global.html#getBrowserAlias">getBrowserAlias</a></li><li><a href="global.html#getBrowserTypeByAlias">getBrowserTypeByAlias</a></li><li><a href="global.html#getFirstMatch">getFirstMatch</a></li><li><a href="global.html#getMacOSVersionName">getMacOSVersionName</a></li><li><a href="global.html#getSecondMatch">getSecondMatch</a></li><li><a href="global.html#getVersionPrecision">getVersionPrecision</a></li><li><a href="global.html#map">map</a></li><li><a href="global.html#matchAndReturnConst">matchAndReturnConst</a></li></ul>
</nav>
<div id="main">
<section class="package">
<h3> </h3>
</section>
<section class="readme">
<article><h2>Bowser</h2>
<p>A small, fast and rich-API browser/platform/engine detector for both browser and node.</p>
<ul>
<li><strong>Small.</strong> Use plain ES5-version which is ~4.8kB gzipped.</li>
<li><strong>Optimized.</strong> Use only those parsers you need — it doesn't do useless work.</li>
<li><strong>Multi-platform.</strong> It's browser- and node-ready, so you can use it in any environment.</li>
</ul>
<p>Don't hesitate to support the project on Github or <a href="https://opencollective.com/bowser">OpenCollective</a> if you like it ❤️ Also, contributors are always welcome!</p>
<p><a href="https://opencollective.com/bowser"><img src="https://opencollective.com/bowser/all/badge.svg?label=financial+contributors" alt="Financial Contributors on Open Collective"></a> <a href="https://travis-ci.org/lancedikson/bowser/"><img src="https://travis-ci.org/lancedikson/bowser.svg?branch=master" alt="Build Status"></a> <a href="https://greenkeeper.io/"><img src="https://badges.greenkeeper.io/lancedikson/bowser.svg" alt="Greenkeeper badge"></a> <a href="https://coveralls.io/github/lancedikson/bowser?branch=master"><img src="https://coveralls.io/repos/github/lancedikson/bowser/badge.svg?branch=master" alt="Coverage Status"></a> <img src="https://img.shields.io/npm/dm/bowser" alt="Downloads"></p>
<h1>Contents</h1>
<ul>
<li><a href="#overview">Overview</a></li>
<li><a href="#use-cases">Use cases</a></li>
<li><a href="#advanced-usage">Advanced usage</a></li>
<li><a href="#contributing">How can I help?</a></li>
</ul>
<h1>Overview</h1>
<p>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. Check it out on this page: https://bowser-js.github.io/bowser-online/.</p>
<h3>⚠️ Version 2.0 breaking changes ⚠️</h3>
<p>Version 2.0 has drastically changed the API. All available methods are on the <a href="https://lancedikson.github.io/bowser/docs">docs page</a>.</p>
<p><em>For legacy code, check out the <a href="https://github.com/lancedikson/bowser/tree/v1.x">1.x</a> branch and install it through <code>npm install bowser@1.9.4</code>.</em></p>
<h1>Use cases</h1>
<p>First of all, require the library. This is a UMD Module, so it will work for AMD, TypeScript, ES6, and CommonJS module systems.</p>
<pre class="prettyprint source lang-javascript"><code>const Bowser = require(&quot;bowser&quot;); // CommonJS
import * as Bowser from &quot;bowser&quot;; // TypeScript
import Bowser from &quot;bowser&quot;; // ES6 (and TypeScript with --esModuleInterop enabled)
</code></pre>
<p>By default, the exported version is the <em>ES5 transpiled version</em>, which <strong>do not</strong> include any polyfills.</p>
<p>In case you don't use your own <code>babel-polyfill</code> you may need to have pre-built bundle with all needed polyfills.
So, for you it's suitable to require bowser like this: <code>require('bowser/bundled')</code>.
As the result, you get a ES5 version of bowser with <code>babel-polyfill</code> bundled together.</p>
<p>You may need to use the source files, so they will be available in the package as well.</p>
<h2>Browser props detection</h2>
<p>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:</p>
<pre class="prettyprint source lang-javascript"><code>const browser = Bowser.getParser(window.navigator.userAgent);
console.log(`The current browser name is &quot;${browser.getBrowserName()}&quot;`);
// The current browser name is &quot;Internet Explorer&quot;
</code></pre>
<p>or</p>
<pre class="prettyprint source lang-javascript"><code>const browser = Bowser.getParser(window.navigator.userAgent);
console.log(browser.getBrowser());
// outputs
{
name: &quot;Internet Explorer&quot;
version: &quot;11.0&quot;
}
</code></pre>
<p>or</p>
<pre class="prettyprint source lang-javascript"><code>console.log(Bowser.parse(window.navigator.userAgent));
// outputs
{
browser: {
name: &quot;Internet Explorer&quot;
version: &quot;11.0&quot;
},
os: {
name: &quot;Windows&quot;
version: &quot;NT 6.3&quot;
versionName: &quot;8.1&quot;
},
platform: {
type: &quot;desktop&quot;
},
engine: {
name: &quot;Trident&quot;
version: &quot;7.0&quot;
}
}
</code></pre>
<h2>Filtering browsers</h2>
<p>You could want to filter some particular browsers to provide any special support for them or make any workarounds.
It could look like this:</p>
<pre class="prettyprint source lang-javascript"><code>const browser = Bowser.getParser(window.navigator.userAgent);
const isValidBrowser = browser.satisfies({
// declare browsers per OS
windows: {
&quot;internet explorer&quot;: &quot;>10&quot;,
},
macos: {
safari: &quot;>10.1&quot;
},
// per platform (mobile, desktop or tablet)
mobile: {
safari: '>=9',
'android browser': '>3.10'
},
// or in general
chrome: &quot;~20.1.1432&quot;,
firefox: &quot;>31&quot;,
opera: &quot;>=22&quot;,
// also supports equality operator
chrome: &quot;=20.1.1432&quot;, // will match particular build only
// and loose-equality operator
chrome: &quot;~20&quot;, // will match any 20.* sub-version
chrome: &quot;~20.1&quot; // will match any 20.1.* sub-version (20.1.19 as well as 20.1.12.42-alpha.1)
});
</code></pre>
<p>Settings for any particular OS or platform has more priority and redefines settings of standalone browsers.
Thus, you can define OS or platform specific rules and they will have more priority in the end.</p>
<p>More of API and possibilities you will find in the <code>docs</code> folder.</p>
<h3>Browser names for <code>.satisfies()</code></h3>
<p>By default you are supposed to use the full browser name for <code>.satisfies</code>.
But, there's a short way to define a browser using short aliases. The full
list of aliases can be found in <a href="src/constants.js">the file</a>.</p>
<h2>Similar Projects</h2>
<ul>
<li><a href="https://github.com/BigBadBleuCheese/Kong">Kong</a> - A C# port of Bowser.</li>
</ul>
<h2>Contributors</h2>
<h3>Code Contributors</h3>
<p>This project exists thanks to all the people who contribute. [<a href="CONTRIBUTING.md">Contribute</a>].
<a href="https://github.com/lancedikson/bowser/graphs/contributors"><img src="https://opencollective.com/bowser/contributors.svg?width=890&button=false" /></a></p>
<h3>Financial Contributors</h3>
<p>Become a financial contributor and help us sustain our community. [<a href="https://opencollective.com/bowser/contribute">Contribute</a>]</p>
<h4>Individuals</h4>
<p><a href="https://opencollective.com/bowser"><img src="https://opencollective.com/bowser/individuals.svg?width=890"></a></p>
<h4>Organizations</h4>
<p>Support this project with your organization. Your logo will show up here with a link to your website. [<a href="https://opencollective.com/bowser/contribute">Contribute</a>]</p>
<p><a href="https://opencollective.com/bowser/organization/0/website"><img src="https://opencollective.com/bowser/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/1/website"><img src="https://opencollective.com/bowser/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/2/website"><img src="https://opencollective.com/bowser/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/3/website"><img src="https://opencollective.com/bowser/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/4/website"><img src="https://opencollective.com/bowser/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/5/website"><img src="https://opencollective.com/bowser/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/6/website"><img src="https://opencollective.com/bowser/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/7/website"><img src="https://opencollective.com/bowser/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/8/website"><img src="https://opencollective.com/bowser/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/bowser/organization/9/website"><img src="https://opencollective.com/bowser/organization/9/avatar.svg"></a></p>
<h2>License</h2>
<p>Licensed as MIT. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.</p></article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Sat Sep 12 2020 11:21:13 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>

565
docs/parser.js.html Normal file
View File

@ -0,0 +1,565 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>parser.js - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Bowser.html">Bowser</a><ul class='methods'><li data-type='method'><a href="Bowser.html#.getParser">getParser</a></li><li data-type='method'><a href="Bowser.html#.parse">parse</a></li></ul></li><li><a href="Parser.html">Parser</a><ul class='methods'><li data-type='method'><a href="Parser.html#getBrowser">getBrowser</a></li><li data-type='method'><a href="Parser.html#getBrowserName">getBrowserName</a></li><li data-type='method'><a href="Parser.html#getBrowserVersion">getBrowserVersion</a></li><li data-type='method'><a href="Parser.html#getEngine">getEngine</a></li><li data-type='method'><a href="Parser.html#getEngineName">getEngineName</a></li><li data-type='method'><a href="Parser.html#getOS">getOS</a></li><li data-type='method'><a href="Parser.html#getOSName">getOSName</a></li><li data-type='method'><a href="Parser.html#getOSVersion">getOSVersion</a></li><li data-type='method'><a href="Parser.html#getPlatform">getPlatform</a></li><li data-type='method'><a href="Parser.html#getPlatformType">getPlatformType</a></li><li data-type='method'><a href="Parser.html#getResult">getResult</a></li><li data-type='method'><a href="Parser.html#getUA">getUA</a></li><li data-type='method'><a href="Parser.html#is">is</a></li><li data-type='method'><a href="Parser.html#isBrowser">isBrowser</a></li><li data-type='method'><a href="Parser.html#parse">parse</a></li><li data-type='method'><a href="Parser.html#parseBrowser">parseBrowser</a></li><li data-type='method'><a href="Parser.html#parseEngine">parseEngine</a></li><li data-type='method'><a href="Parser.html#parseOS">parseOS</a></li><li data-type='method'><a href="Parser.html#parsePlatform">parsePlatform</a></li><li data-type='method'><a href="Parser.html#satisfies">satisfies</a></li><li data-type='method'><a href="Parser.html#some">some</a></li><li data-type='method'><a href="Parser.html#test">test</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#assign">assign</a></li><li><a href="global.html#find">find</a></li><li><a href="global.html#getAndroidVersionName">getAndroidVersionName</a></li><li><a href="global.html#getBrowserAlias">getBrowserAlias</a></li><li><a href="global.html#getBrowserTypeByAlias">getBrowserTypeByAlias</a></li><li><a href="global.html#getFirstMatch">getFirstMatch</a></li><li><a href="global.html#getMacOSVersionName">getMacOSVersionName</a></li><li><a href="global.html#getSecondMatch">getSecondMatch</a></li><li><a href="global.html#getVersionPrecision">getVersionPrecision</a></li><li><a href="global.html#map">map</a></li><li><a href="global.html#matchAndReturnConst">matchAndReturnConst</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">parser.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>import browserParsersList from './parser-browsers.js';
import osParsersList from './parser-os.js';
import platformParsersList from './parser-platforms.js';
import enginesParsersList from './parser-engines.js';
import Utils from './utils.js';
/**
* The main class that arranges the whole parsing process.
*/
class Parser {
/**
* Create instance of Parser
*
* @param {String} UA User-Agent string
* @param {Boolean} [skipParsing=false] parser can skip parsing in purpose of performance
* improvements if you need to make a more particular parsing
* like {@link Parser#parseBrowser} or {@link Parser#parsePlatform}
*
* @throw {Error} in case of empty UA String
*
* @constructor
*/
constructor(UA, skipParsing = false) {
if (UA === void (0) || UA === null || UA === '') {
throw new Error("UserAgent parameter can't be empty");
}
this._ua = UA;
/**
* @typedef ParsedResult
* @property {Object} browser
* @property {String|undefined} [browser.name]
* Browser name, like `"Chrome"` or `"Internet Explorer"`
* @property {String|undefined} [browser.version] Browser version as a String `"12.01.45334.10"`
* @property {Object} os
* @property {String|undefined} [os.name] OS name, like `"Windows"` or `"macOS"`
* @property {String|undefined} [os.version] OS version, like `"NT 5.1"` or `"10.11.1"`
* @property {String|undefined} [os.versionName] OS name, like `"XP"` or `"High Sierra"`
* @property {Object} platform
* @property {String|undefined} [platform.type]
* platform type, can be either `"desktop"`, `"tablet"` or `"mobile"`
* @property {String|undefined} [platform.vendor] Vendor of the device,
* like `"Apple"` or `"Samsung"`
* @property {String|undefined} [platform.model] Device model,
* like `"iPhone"` or `"Kindle Fire HD 7"`
* @property {Object} engine
* @property {String|undefined} [engine.name]
* Can be any of this: `WebKit`, `Blink`, `Gecko`, `Trident`, `Presto`, `EdgeHTML`
* @property {String|undefined} [engine.version] String version of the engine
*/
this.parsedResult = {};
if (skipParsing !== true) {
this.parse();
}
}
/**
* Get UserAgent string of current Parser instance
* @return {String} User-Agent String of the current &lt;Parser> object
*
* @public
*/
getUA() {
return this._ua;
}
/**
* Test a UA string for a regexp
* @param {RegExp} regex
* @return {Boolean}
*/
test(regex) {
return regex.test(this._ua);
}
/**
* Get parsed browser object
* @return {Object}
*/
parseBrowser() {
this.parsedResult.browser = {};
const browserDescriptor = Utils.find(browserParsersList, (_browser) => {
if (typeof _browser.test === 'function') {
return _browser.test(this);
}
if (_browser.test instanceof Array) {
return _browser.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (browserDescriptor) {
this.parsedResult.browser = browserDescriptor.describe(this.getUA());
}
return this.parsedResult.browser;
}
/**
* Get parsed browser object
* @return {Object}
*
* @public
*/
getBrowser() {
if (this.parsedResult.browser) {
return this.parsedResult.browser;
}
return this.parseBrowser();
}
/**
* Get browser's name
* @return {String} Browser's name or an empty string
*
* @public
*/
getBrowserName(toLowerCase) {
if (toLowerCase) {
return String(this.getBrowser().name).toLowerCase() || '';
}
return this.getBrowser().name || '';
}
/**
* Get browser's version
* @return {String} version of browser
*
* @public
*/
getBrowserVersion() {
return this.getBrowser().version;
}
/**
* Get OS
* @return {Object}
*
* @example
* this.getOS();
* {
* name: 'macOS',
* version: '10.11.12'
* }
*/
getOS() {
if (this.parsedResult.os) {
return this.parsedResult.os;
}
return this.parseOS();
}
/**
* Parse OS and save it to this.parsedResult.os
* @return {*|{}}
*/
parseOS() {
this.parsedResult.os = {};
const os = Utils.find(osParsersList, (_os) => {
if (typeof _os.test === 'function') {
return _os.test(this);
}
if (_os.test instanceof Array) {
return _os.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (os) {
this.parsedResult.os = os.describe(this.getUA());
}
return this.parsedResult.os;
}
/**
* Get OS name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} name of the OS — macOS, Windows, Linux, etc.
*/
getOSName(toLowerCase) {
const { name } = this.getOS();
if (toLowerCase) {
return String(name).toLowerCase() || '';
}
return name || '';
}
/**
* Get OS version
* @return {String} full version with dots ('10.11.12', '5.6', etc)
*/
getOSVersion() {
return this.getOS().version;
}
/**
* Get parsed platform
* @return {{}}
*/
getPlatform() {
if (this.parsedResult.platform) {
return this.parsedResult.platform;
}
return this.parsePlatform();
}
/**
* Get platform name
* @param {Boolean} [toLowerCase=false]
* @return {*}
*/
getPlatformType(toLowerCase = false) {
const { type } = this.getPlatform();
if (toLowerCase) {
return String(type).toLowerCase() || '';
}
return type || '';
}
/**
* Get parsed platform
* @return {{}}
*/
parsePlatform() {
this.parsedResult.platform = {};
const platform = Utils.find(platformParsersList, (_platform) => {
if (typeof _platform.test === 'function') {
return _platform.test(this);
}
if (_platform.test instanceof Array) {
return _platform.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (platform) {
this.parsedResult.platform = platform.describe(this.getUA());
}
return this.parsedResult.platform;
}
/**
* Get parsed engine
* @return {{}}
*/
getEngine() {
if (this.parsedResult.engine) {
return this.parsedResult.engine;
}
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 {{}}
*/
parseEngine() {
this.parsedResult.engine = {};
const engine = Utils.find(enginesParsersList, (_engine) => {
if (typeof _engine.test === 'function') {
return _engine.test(this);
}
if (_engine.test instanceof Array) {
return _engine.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (engine) {
this.parsedResult.engine = engine.describe(this.getUA());
}
return this.parsedResult.engine;
}
/**
* Parse full information about the browser
* @returns {Parser}
*/
parse() {
this.parseBrowser();
this.parseOS();
this.parsePlatform();
this.parseEngine();
return this;
}
/**
* Get parsed result
* @return {ParsedResult}
*/
getResult() {
return Utils.assign({}, this.parsedResult);
}
/**
* Check if parsed browser matches certain conditions
*
* @param {Object} checkTree It's one or two layered object,
* which can include a platform or an OS on the first layer
* and should have browsers specs on the bottom-laying layer
*
* @returns {Boolean|undefined} Whether the browser satisfies the set conditions or not.
* Returns `undefined` when the browser is no described in the checkTree object.
*
* @example
* const browser = Bowser.getParser(window.navigator.userAgent);
* if (browser.satisfies({chrome: '>118.01.1322' }))
* // or with os
* if (browser.satisfies({windows: { chrome: '>118.01.1322' } }))
* // or with platforms
* if (browser.satisfies({desktop: { chrome: '>118.01.1322' } }))
*/
satisfies(checkTree) {
const platformsAndOSes = {};
let platformsAndOSCounter = 0;
const browsers = {};
let browsersCounter = 0;
const allDefinitions = Object.keys(checkTree);
allDefinitions.forEach((key) => {
const currentDefinition = checkTree[key];
if (typeof currentDefinition === 'string') {
browsers[key] = currentDefinition;
browsersCounter += 1;
} else if (typeof currentDefinition === 'object') {
platformsAndOSes[key] = currentDefinition;
platformsAndOSCounter += 1;
}
});
if (platformsAndOSCounter > 0) {
const platformsAndOSNames = Object.keys(platformsAndOSes);
const OSMatchingDefinition = Utils.find(platformsAndOSNames, name => (this.isOS(name)));
if (OSMatchingDefinition) {
const osResult = this.satisfies(platformsAndOSes[OSMatchingDefinition]);
if (osResult !== void 0) {
return osResult;
}
}
const platformMatchingDefinition = Utils.find(
platformsAndOSNames,
name => (this.isPlatform(name)),
);
if (platformMatchingDefinition) {
const platformResult = this.satisfies(platformsAndOSes[platformMatchingDefinition]);
if (platformResult !== void 0) {
return platformResult;
}
}
}
if (browsersCounter > 0) {
const browserNames = Object.keys(browsers);
const matchingDefinition = Utils.find(browserNames, name => (this.isBrowser(name, true)));
if (matchingDefinition !== void 0) {
return this.compareVersion(browsers[matchingDefinition]);
}
}
return undefined;
}
/**
* Check if the browser name equals the passed string
* @param browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName, includingAlias = false) {
const defaultBrowserName = this.getBrowserName().toLowerCase();
let browserNameLower = browserName.toLowerCase();
const alias = Utils.getBrowserTypeByAlias(browserNameLower);
if (includingAlias &amp;&amp; alias) {
browserNameLower = alias.toLowerCase();
}
return browserNameLower === defaultBrowserName;
}
compareVersion(version) {
let expectedResults = [0];
let comparableVersion = version;
let isLoose = false;
const currentBrowserVersion = this.getBrowserVersion();
if (typeof currentBrowserVersion !== 'string') {
return void 0;
}
if (version[0] === '>' || version[0] === '&lt;') {
comparableVersion = version.substr(1);
if (version[1] === '=') {
isLoose = true;
comparableVersion = version.substr(2);
} else {
expectedResults = [];
}
if (version[0] === '>') {
expectedResults.push(1);
} else {
expectedResults.push(-1);
}
} else if (version[0] === '=') {
comparableVersion = version.substr(1);
} else if (version[0] === '~') {
isLoose = true;
comparableVersion = version.substr(1);
}
return expectedResults.indexOf(
Utils.compareVersions(currentBrowserVersion, comparableVersion, isLoose),
) > -1;
}
isOS(osName) {
return this.getOSName(true) === String(osName).toLowerCase();
}
isPlatform(platformType) {
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"
* @param {String} anything
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {Boolean}
*/
is(anything, includingAlias = false) {
return this.isBrowser(anything, includingAlias) || this.isOS(anything)
|| this.isPlatform(anything);
}
/**
* Check if any of the given values satisfies this.is(anything)
* @param {String[]} anythings
* @returns {Boolean}
*/
some(anythings = []) {
return anythings.some(anything => this.is(anything));
}
}
export default Parser;
</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Sat Sep 12 2020 11:21:13 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>

20
docs/scripts/collapse.js Normal file
View File

@ -0,0 +1,20 @@
function hideAllButCurrent(){
//by default all submenut items are hidden
//but we need to rehide them for search
document.querySelectorAll("nav > ul > li > ul li").forEach(function(parent) {
parent.style.display = "none";
});
//only current page (if it exists) should be opened
var file = window.location.pathname.split("/").pop().replace(/\.html/, '');
document.querySelectorAll("nav > ul > li > a").forEach(function(parent) {
var href = parent.attributes.href.value.replace(/\.html/, '');
if (file === href) {
parent.parentNode.querySelectorAll("ul li").forEach(function(elem) {
elem.style.display = "block";
});
}
});
}
hideAllButCurrent();

4
docs/scripts/jquery-3.1.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,25 @@
/*global document */
(function() {
var source = document.getElementsByClassName('prettyprint source linenums');
var i = 0;
var lineNumber = 0;
var lineId;
var lines;
var totalLines;
var anchorHash;
if (source && source[0]) {
anchorHash = document.location.hash.substring(1);
lines = source[0].getElementsByTagName('li');
totalLines = lines.length;
for (; i < totalLines; i++) {
lineNumber++;
lineId = 'line' + lineNumber;
lines[i].id = lineId;
if (lineId === anchorHash) {
lines[i].className += ' selected';
}
}
}
})();

12
docs/scripts/nav.js Normal file
View File

@ -0,0 +1,12 @@
function scrollToNavItem() {
var path = window.location.href.split('/').pop().replace(/\.html/, '');
document.querySelectorAll('nav a').forEach(function(link) {
var href = link.attributes.href.value.replace(/\.html/, '');
if (path === href) {
link.scrollIntoView({block: 'center'});
return;
}
})
}
scrollToNavItem();

4
docs/scripts/polyfill.js Normal file
View File

@ -0,0 +1,4 @@
//IE Fix, src: https://www.reddit.com/r/programminghorror/comments/6abmcr/nodelist_lacks_foreach_in_internet_explorer/
if (typeof(NodeList.prototype.forEach)!==typeof(alert)){
NodeList.prototype.forEach=Array.prototype.forEach;
}

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,2 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

View File

@ -0,0 +1,28 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

83
docs/scripts/search.js Normal file
View File

@ -0,0 +1,83 @@
var searchAttr = 'data-search-mode';
function contains(a,m){
return (a.textContent || a.innerText || "").toUpperCase().indexOf(m) !== -1;
};
//on search
document.getElementById("nav-search").addEventListener("keyup", function(event) {
var search = this.value.toUpperCase();
if (!search) {
//no search, show all results
document.documentElement.removeAttribute(searchAttr);
document.querySelectorAll("nav > ul > li:not(.level-hide)").forEach(function(elem) {
elem.style.display = "block";
});
if (typeof hideAllButCurrent === "function"){
//let's do what ever collapse wants to do
hideAllButCurrent();
} else {
//menu by default should be opened
document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) {
elem.style.display = "block";
});
}
} else {
//we are searching
document.documentElement.setAttribute(searchAttr, '');
//show all parents
document.querySelectorAll("nav > ul > li").forEach(function(elem) {
elem.style.display = "block";
});
//hide all results
document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) {
elem.style.display = "none";
});
//show results matching filter
document.querySelectorAll("nav > ul > li > ul a").forEach(function(elem) {
if (!contains(elem.parentNode, search)) {
return;
}
elem.parentNode.style.display = "block";
});
//hide parents without children
document.querySelectorAll("nav > ul > li").forEach(function(parent) {
var countSearchA = 0;
parent.querySelectorAll("a").forEach(function(elem) {
if (contains(elem, search)) {
countSearchA++;
}
});
var countUl = 0;
var countUlVisible = 0;
parent.querySelectorAll("ul").forEach(function(ulP) {
// count all elements that match the search
if (contains(ulP, search)) {
countUl++;
}
// count all visible elements
var children = ulP.children
for (i=0; i<children.length; i++) {
var elem = children[i];
if (elem.style.display != "none") {
countUlVisible++;
}
}
});
if (countSearchA == 0 && countUl === 0){
//has no child at all and does not contain text
parent.style.display = "none";
} else if(countSearchA == 0 && countUlVisible == 0){
//has no visible child and does not contain text
parent.style.display = "none";
}
});
}
});

671
docs/styles/jsdoc.css Normal file
View File

@ -0,0 +1,671 @@
@import url(https://fonts.googleapis.com/css?family=Montserrat:400,700);
* {
box-sizing: border-box
}
html, body {
height: 100%;
width: 100%;
}
body {
color: #4d4e53;
background-color: white;
margin: 0 auto;
padding: 0 20px;
font-family: 'Helvetica Neue', Helvetica, sans-serif;
font-size: 16px;
}
img {
max-width: 100%;
}
a,
a:active {
color: #606;
text-decoration: none;
}
a:hover {
text-decoration: none;
}
article a {
border-bottom: 1px solid #ddd;
}
article a:hover, article a:active {
border-bottom-color: #222;
}
article .description a {
word-break: break-word;
}
p, ul, ol, blockquote {
margin-bottom: 1em;
line-height: 160%;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Montserrat', sans-serif;
}
h1, h2, h3, h4, h5, h6 {
color: #000;
font-weight: 400;
margin: 0;
}
h1 {
font-weight: 300;
font-size: 48px;
margin: 1em 0 .5em;
}
h1.page-title {
font-size: 48px;
margin: 1em 30px;
line-height: 100%;
word-wrap: break-word;
}
h2 {
font-size: 24px;
margin: 1.5em 0 .3em;
}
h3 {
font-size: 24px;
margin: 1.2em 0 .3em;
}
h4 {
font-size: 18px;
margin: 1em 0 .2em;
color: #4d4e53;
}
h4.name {
color: #fff;
background: #6d426d;
box-shadow: 0 .25em .5em #d3d3d3;
border-top: 1px solid #d3d3d3;
border-bottom: 1px solid #d3d3d3;
margin: 1.5em 0 0.5em;
padding: .75em 0 .75em 10px;
}
h4.name a {
color: #fc83ff;
}
h4.name a:hover {
border-bottom-color: #fc83ff;
}
h5, .container-overview .subsection-title {
font-size: 120%;
letter-spacing: -0.01em;
margin: 8px 0 3px 0;
}
h6 {
font-size: 100%;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
font-style: italic;
}
tt, code, kbd, samp {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
background: #f4f4f4;
padding: 1px 5px;
}
.class-description {
font-size: 130%;
line-height: 140%;
margin-bottom: 1em;
margin-top: 1em;
}
.class-description:empty {
margin: 0
}
#main {
float: right;
min-width: 360px;
width: calc(100% - 240px);
}
header {
display: block
}
section {
display: block;
background-color: #fff;
padding: 0 0 0 30px;
}
.variation {
display: none
}
.signature-attributes {
font-size: 60%;
color: #eee;
font-style: italic;
font-weight: lighter;
}
nav {
float: left;
display: block;
width: 250px;
background: #fff;
overflow: auto;
position: fixed;
height: 100%;
}
nav #nav-search{
width: 210px;
height: 30px;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
margin-right: 20px;
margin-top: 20px;
}
nav.wrap a{
word-wrap: break-word;
}
nav h3 {
margin-top: 12px;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 700;
line-height: 24px;
margin: 15px 0 10px;
padding: 0;
color: #000;
}
nav ul {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
font-size: 100%;
line-height: 17px;
padding: 0;
margin: 0;
list-style-type: none;
}
nav ul a,
nav ul a:active {
font-family: 'Montserrat', sans-serif;
line-height: 18px;
padding: 0;
display: block;
font-size: 12px;
}
nav a:hover,
nav a:active {
color: #606;
}
nav > ul {
padding: 0 10px;
}
nav > ul > li > a {
color: #606;
margin-top: 10px;
}
nav ul ul a {
color: hsl(207, 1%, 60%);
border-left: 1px solid hsl(207, 10%, 86%);
}
nav ul ul a,
nav ul ul a:active {
padding-left: 20px
}
nav h2 {
font-size: 13px;
margin: 10px 0 0 0;
padding: 0;
}
nav > h2 > a {
margin: 10px 0 -10px;
color: #606 !important;
}
footer {
color: hsl(0, 0%, 28%);
margin-left: 250px;
display: block;
padding: 15px;
font-style: italic;
font-size: 90%;
}
.ancestors {
color: #999
}
.ancestors a {
color: #999 !important;
}
.clear {
clear: both
}
.important {
font-weight: bold;
color: #950B02;
}
.yes-def {
text-indent: -1000px
}
.type-signature {
color: #CA79CA
}
.type-signature:last-child {
color: #eee;
}
.name, .signature {
font-family: Consolas, Monaco, 'Andale Mono', monospace
}
.signature {
color: #fc83ff;
}
.details {
margin-top: 6px;
border-left: 2px solid #DDD;
line-height: 20px;
font-size: 14px;
}
.details dt {
width: auto;
float: left;
padding-left: 10px;
}
.details dd {
margin-left: 70px;
margin-top: 6px;
margin-bottom: 6px;
}
.details ul {
margin: 0
}
.details ul {
list-style-type: none
}
.details pre.prettyprint {
margin: 0
}
.details .object-value {
padding-top: 0
}
.description {
margin-bottom: 1em;
margin-top: 1em;
}
.code-caption {
font-style: italic;
font-size: 107%;
margin: 0;
}
.prettyprint {
font-size: 14px;
overflow: auto;
}
.prettyprint.source {
width: inherit;
line-height: 18px;
display: block;
background-color: #0d152a;
color: #aeaeae;
}
.prettyprint code {
line-height: 18px;
display: block;
background-color: #0d152a;
color: #4D4E53;
}
.prettyprint > code {
padding: 15px;
}
.prettyprint .linenums code {
padding: 0 15px
}
.prettyprint .linenums li:first-of-type code {
padding-top: 15px
}
.prettyprint code span.line {
display: inline-block
}
.prettyprint.linenums {
padding-left: 70px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.prettyprint.linenums ol {
padding-left: 0
}
.prettyprint.linenums li {
border-left: 3px #34446B solid;
}
.prettyprint.linenums li.selected, .prettyprint.linenums li.selected * {
background-color: #34446B;
}
.prettyprint.linenums li * {
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
table {
border-spacing: 0;
border: 1px solid #ddd;
border-collapse: collapse;
border-radius: 3px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
width: 100%;
font-size: 14px;
margin: 1em 0;
}
td, th {
margin: 0px;
text-align: left;
vertical-align: top;
padding: 10px;
display: table-cell;
}
thead tr, thead tr {
background-color: #fff;
font-weight: bold;
border-bottom: 1px solid #ddd;
}
.params .type {
white-space: nowrap;
}
.params code {
white-space: pre;
}
.params td, .params .name, .props .name, .name code {
color: #4D4E53;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 100%;
}
.params td {
border-top: 1px solid #eee
}
.params td.description > p:first-child, .props td.description > p:first-child {
margin-top: 0;
padding-top: 0;
}
.params td.description > p:last-child, .props td.description > p:last-child {
margin-bottom: 0;
padding-bottom: 0;
}
span.param-type, .params td .param-type, .param-type dd {
color: #606;
font-family: Consolas, Monaco, 'Andale Mono', monospace
}
.param-type dt, .param-type dd {
display: inline-block
}
.param-type {
margin: 14px 0;
}
.disabled {
color: #454545
}
/* navicon button */
.navicon-button {
display: none;
position: relative;
padding: 2.0625rem 1.5rem;
transition: 0.25s;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
opacity: .8;
}
.navicon-button .navicon:before, .navicon-button .navicon:after {
transition: 0.25s;
}
.navicon-button:hover {
transition: 0.5s;
opacity: 1;
}
.navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after {
transition: 0.25s;
}
.navicon-button:hover .navicon:before {
top: .825rem;
}
.navicon-button:hover .navicon:after {
top: -.825rem;
}
/* navicon */
.navicon {
position: relative;
width: 2.5em;
height: .3125rem;
background: #000;
transition: 0.3s;
border-radius: 2.5rem;
}
.navicon:before, .navicon:after {
display: block;
content: "";
height: .3125rem;
width: 2.5rem;
background: #000;
position: absolute;
z-index: -1;
transition: 0.3s 0.25s;
border-radius: 1rem;
}
.navicon:before {
top: .625rem;
}
.navicon:after {
top: -.625rem;
}
/* open */
.nav-trigger:checked + label:not(.steps) .navicon:before,
.nav-trigger:checked + label:not(.steps) .navicon:after {
top: 0 !important;
}
.nav-trigger:checked + label .navicon:before,
.nav-trigger:checked + label .navicon:after {
transition: 0.5s;
}
/* Minus */
.nav-trigger:checked + label {
-webkit-transform: scale(0.75);
transform: scale(0.75);
}
/* × and + */
.nav-trigger:checked + label.plus .navicon,
.nav-trigger:checked + label.x .navicon {
background: transparent;
}
.nav-trigger:checked + label.plus .navicon:before,
.nav-trigger:checked + label.x .navicon:before {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
background: #FFF;
}
.nav-trigger:checked + label.plus .navicon:after,
.nav-trigger:checked + label.x .navicon:after {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
background: #FFF;
}
.nav-trigger:checked + label.plus {
-webkit-transform: scale(0.75) rotate(45deg);
transform: scale(0.75) rotate(45deg);
}
.nav-trigger:checked ~ nav {
left: 0 !important;
}
.nav-trigger:checked ~ .overlay {
display: block;
}
.nav-trigger {
position: fixed;
top: 0;
clip: rect(0, 0, 0, 0);
}
.overlay {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
background: hsla(0, 0%, 0%, 0.5);
z-index: 1;
}
/* nav level */
.level-hide {
display: none;
}
html[data-search-mode] .level-hide {
display: block;
}
@media only screen and (min-width: 320px) and (max-width: 680px) {
body {
overflow-x: hidden;
}
nav {
background: #FFF;
width: 250px;
height: 100%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: -250px;
z-index: 3;
padding: 0 10px;
transition: left 0.2s;
}
.navicon-button {
display: inline-block;
position: fixed;
top: 1.5em;
right: 0;
z-index: 2;
}
#main {
width: 100%;
min-width: 360px;
}
#main h1.page-title {
margin: 1em 0;
}
#main section {
padding: 0;
}
footer {
margin-left: 0;
}
}
/** Add a '#' to static members */
[data-type="member"] a::before {
content: '#';
display: inline-block;
margin-left: -14px;
margin-right: 5px;
}
#disqus_thread{
margin-left: 30px;
}

79
docs/styles/prettify.css Normal file
View File

@ -0,0 +1,79 @@
.pln {
color: #ddd;
}
/* string content */
.str {
color: #61ce3c;
}
/* a keyword */
.kwd {
color: #fbde2d;
}
/* a comment */
.com {
color: #aeaeae;
}
/* a type name */
.typ {
color: #8da6ce;
}
/* a literal value */
.lit {
color: #fbde2d;
}
/* punctuation */
.pun {
color: #ddd;
}
/* lisp open bracket */
.opn {
color: #000000;
}
/* lisp close bracket */
.clo {
color: #000000;
}
/* a markup tag name */
.tag {
color: #8da6ce;
}
/* a markup attribute name */
.atn {
color: #fbde2d;
}
/* a markup attribute value */
.atv {
color: #ddd;
}
/* a declaration */
.dec {
color: #EF5050;
}
/* a variable name */
.var {
color: #c82829;
}
/* a function name */
.fun {
color: #4271ae;
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}

378
docs/utils.js.html Normal file
View File

@ -0,0 +1,378 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>utils.js - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Bowser.html">Bowser</a><ul class='methods'><li data-type='method'><a href="Bowser.html#.getParser">getParser</a></li><li data-type='method'><a href="Bowser.html#.parse">parse</a></li></ul></li><li><a href="Parser.html">Parser</a><ul class='methods'><li data-type='method'><a href="Parser.html#getBrowser">getBrowser</a></li><li data-type='method'><a href="Parser.html#getBrowserName">getBrowserName</a></li><li data-type='method'><a href="Parser.html#getBrowserVersion">getBrowserVersion</a></li><li data-type='method'><a href="Parser.html#getEngine">getEngine</a></li><li data-type='method'><a href="Parser.html#getEngineName">getEngineName</a></li><li data-type='method'><a href="Parser.html#getOS">getOS</a></li><li data-type='method'><a href="Parser.html#getOSName">getOSName</a></li><li data-type='method'><a href="Parser.html#getOSVersion">getOSVersion</a></li><li data-type='method'><a href="Parser.html#getPlatform">getPlatform</a></li><li data-type='method'><a href="Parser.html#getPlatformType">getPlatformType</a></li><li data-type='method'><a href="Parser.html#getResult">getResult</a></li><li data-type='method'><a href="Parser.html#getUA">getUA</a></li><li data-type='method'><a href="Parser.html#is">is</a></li><li data-type='method'><a href="Parser.html#isBrowser">isBrowser</a></li><li data-type='method'><a href="Parser.html#parse">parse</a></li><li data-type='method'><a href="Parser.html#parseBrowser">parseBrowser</a></li><li data-type='method'><a href="Parser.html#parseEngine">parseEngine</a></li><li data-type='method'><a href="Parser.html#parseOS">parseOS</a></li><li data-type='method'><a href="Parser.html#parsePlatform">parsePlatform</a></li><li data-type='method'><a href="Parser.html#satisfies">satisfies</a></li><li data-type='method'><a href="Parser.html#some">some</a></li><li data-type='method'><a href="Parser.html#test">test</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#assign">assign</a></li><li><a href="global.html#find">find</a></li><li><a href="global.html#getAndroidVersionName">getAndroidVersionName</a></li><li><a href="global.html#getBrowserAlias">getBrowserAlias</a></li><li><a href="global.html#getBrowserTypeByAlias">getBrowserTypeByAlias</a></li><li><a href="global.html#getFirstMatch">getFirstMatch</a></li><li><a href="global.html#getMacOSVersionName">getMacOSVersionName</a></li><li><a href="global.html#getSecondMatch">getSecondMatch</a></li><li><a href="global.html#getVersionPrecision">getVersionPrecision</a></li><li><a href="global.html#map">map</a></li><li><a href="global.html#matchAndReturnConst">matchAndReturnConst</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">utils.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>import { BROWSER_MAP, BROWSER_ALIASES_MAP } from './constants.js';
export default class Utils {
/**
* Get first matched item for a string
* @param {RegExp} regexp
* @param {String} ua
* @return {Array|{index: number, input: string}|*|boolean|string}
*/
static getFirstMatch(regexp, ua) {
const match = ua.match(regexp);
return (match &amp;&amp; match.length > 0 &amp;&amp; match[1]) || '';
}
/**
* Get second matched item for a string
* @param regexp
* @param {String} ua
* @return {Array|{index: number, input: string}|*|boolean|string}
*/
static getSecondMatch(regexp, ua) {
const match = ua.match(regexp);
return (match &amp;&amp; match.length > 1 &amp;&amp; match[2]) || '';
}
/**
* Match a regexp and return a constant or undefined
* @param {RegExp} regexp
* @param {String} ua
* @param {*} _const Any const that will be returned if regexp matches the string
* @return {*}
*/
static matchAndReturnConst(regexp, ua, _const) {
if (regexp.test(ua)) {
return _const;
}
return void (0);
}
static getWindowsVersionName(version) {
switch (version) {
case 'NT': return 'NT';
case 'XP': return 'XP';
case 'NT 5.0': return '2000';
case 'NT 5.1': return 'XP';
case 'NT 5.2': return '2003';
case 'NT 6.0': return 'Vista';
case 'NT 6.1': return '7';
case 'NT 6.2': return '8';
case 'NT 6.3': return '8.1';
case 'NT 10.0': return '10';
default: return undefined;
}
}
/**
* Get macOS version name
* 10.5 - Leopard
* 10.6 - Snow Leopard
* 10.7 - Lion
* 10.8 - Mountain Lion
* 10.9 - Mavericks
* 10.10 - Yosemite
* 10.11 - El Capitan
* 10.12 - Sierra
* 10.13 - High Sierra
* 10.14 - Mojave
* 10.15 - Catalina
*
* @example
* getMacOSVersionName("10.14") // 'Mojave'
*
* @param {string} version
* @return {string} versionName
*/
static getMacOSVersionName(version) {
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
v.push(0);
if (v[0] !== 10) return undefined;
switch (v[1]) {
case 5: return 'Leopard';
case 6: return 'Snow Leopard';
case 7: return 'Lion';
case 8: return 'Mountain Lion';
case 9: return 'Mavericks';
case 10: return 'Yosemite';
case 11: return 'El Capitan';
case 12: return 'Sierra';
case 13: return 'High Sierra';
case 14: return 'Mojave';
case 15: return 'Catalina';
default: return undefined;
}
}
/**
* Get Android version name
* 1.5 - Cupcake
* 1.6 - Donut
* 2.0 - Eclair
* 2.1 - Eclair
* 2.2 - Froyo
* 2.x - Gingerbread
* 3.x - Honeycomb
* 4.0 - Ice Cream Sandwich
* 4.1 - Jelly Bean
* 4.4 - KitKat
* 5.x - Lollipop
* 6.x - Marshmallow
* 7.x - Nougat
* 8.x - Oreo
* 9.x - Pie
*
* @example
* getAndroidVersionName("7.0") // 'Nougat'
*
* @param {string} version
* @return {string} versionName
*/
static getAndroidVersionName(version) {
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
v.push(0);
if (v[0] === 1 &amp;&amp; v[1] &lt; 5) return undefined;
if (v[0] === 1 &amp;&amp; v[1] &lt; 6) return 'Cupcake';
if (v[0] === 1 &amp;&amp; v[1] >= 6) return 'Donut';
if (v[0] === 2 &amp;&amp; v[1] &lt; 2) return 'Eclair';
if (v[0] === 2 &amp;&amp; v[1] === 2) return 'Froyo';
if (v[0] === 2 &amp;&amp; v[1] > 2) return 'Gingerbread';
if (v[0] === 3) return 'Honeycomb';
if (v[0] === 4 &amp;&amp; v[1] &lt; 1) return 'Ice Cream Sandwich';
if (v[0] === 4 &amp;&amp; v[1] &lt; 4) return 'Jelly Bean';
if (v[0] === 4 &amp;&amp; v[1] >= 4) return 'KitKat';
if (v[0] === 5) return 'Lollipop';
if (v[0] === 6) return 'Marshmallow';
if (v[0] === 7) return 'Nougat';
if (v[0] === 8) return 'Oreo';
if (v[0] === 9) return 'Pie';
return undefined;
}
/**
* Get version precisions count
*
* @example
* getVersionPrecision("1.10.3") // 3
*
* @param {string} version
* @return {number}
*/
static getVersionPrecision(version) {
return version.split('.').length;
}
/**
* Calculate browser version weight
*
* @example
* compareVersions('1.10.2.1', '1.8.2.1.90') // 1
* compareVersions('1.010.2.1', '1.09.2.1.90'); // 1
* compareVersions('1.10.2.1', '1.10.2.1'); // 0
* compareVersions('1.10.2.1', '1.0800.2'); // -1
* compareVersions('1.10.2.1', '1.10', true); // 0
*
* @param {String} versionA versions versions to compare
* @param {String} versionB versions versions to compare
* @param {boolean} [isLoose] enable loose comparison
* @return {Number} comparison result: -1 when versionA is lower,
* 1 when versionA is bigger, 0 when both equal
*/
/* eslint consistent-return: 1 */
static compareVersions(versionA, versionB, isLoose = false) {
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
const versionAPrecision = Utils.getVersionPrecision(versionA);
const versionBPrecision = Utils.getVersionPrecision(versionB);
let precision = Math.max(versionAPrecision, versionBPrecision);
let lastPrecision = 0;
const chunks = Utils.map([versionA, versionB], (version) => {
const delta = precision - Utils.getVersionPrecision(version);
// 2) "9" -> "9.0" (for precision = 2)
const _version = version + new Array(delta + 1).join('.0');
// 3) "9.0" -> ["000000000"", "000000009"]
return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
});
// adjust precision for loose comparison
if (isLoose) {
lastPrecision = precision - Math.min(versionAPrecision, versionBPrecision);
}
// iterate in reverse order by reversed chunks array
precision -= 1;
while (precision >= lastPrecision) {
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
if (chunks[0][precision] > chunks[1][precision]) {
return 1;
}
if (chunks[0][precision] === chunks[1][precision]) {
if (precision === lastPrecision) {
// all version chunks are same
return 0;
}
precision -= 1;
} else if (chunks[0][precision] &lt; chunks[1][precision]) {
return -1;
}
}
return undefined;
}
/**
* Array::map polyfill
*
* @param {Array} arr
* @param {Function} iterator
* @return {Array}
*/
static map(arr, iterator) {
const result = [];
let i;
if (Array.prototype.map) {
return Array.prototype.map.call(arr, iterator);
}
for (i = 0; i &lt; arr.length; i += 1) {
result.push(iterator(arr[i]));
}
return result;
}
/**
* Array::find polyfill
*
* @param {Array} arr
* @param {Function} predicate
* @return {Array}
*/
static find(arr, predicate) {
let i;
let l;
if (Array.prototype.find) {
return Array.prototype.find.call(arr, predicate);
}
for (i = 0, l = arr.length; i &lt; l; i += 1) {
const value = arr[i];
if (predicate(value, i)) {
return value;
}
}
return undefined;
}
/**
* Object::assign polyfill
*
* @param {Object} obj
* @param {Object} ...objs
* @return {Object}
*/
static assign(obj, ...assigners) {
const result = obj;
let i;
let l;
if (Object.assign) {
return Object.assign(obj, ...assigners);
}
for (i = 0, l = assigners.length; i &lt; l; i += 1) {
const assigner = assigners[i];
if (typeof assigner === 'object' &amp;&amp; assigner !== null) {
const keys = Object.keys(assigner);
keys.forEach((key) => {
result[key] = assigner[key];
});
}
}
return obj;
}
/**
* Get short version/alias for a browser name
*
* @example
* getBrowserAlias('Microsoft Edge') // edge
*
* @param {string} browserName
* @return {string}
*/
static getBrowserAlias(browserName) {
return BROWSER_ALIASES_MAP[browserName];
}
/**
* Get short version/alias for a browser name
*
* @example
* getBrowserAlias('edge') // Microsoft Edge
*
* @param {string} browserAlias
* @return {string}
*/
static getBrowserTypeByAlias(browserAlias) {
return BROWSER_MAP[browserAlias] || '';
}
}
</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Sat Sep 12 2020 11:21:13 GMT+0300 (Eastern European Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>

315
index.d.ts vendored Normal file
View File

@ -0,0 +1,315 @@
// Type definitions for Bowser v2
// Project: https://github.com/lancedikson/bowser
// Definitions by: Alexander P. Cerutti <https://github.com/alexandercerutti>,
export default Bowser;
export as namespace Bowser;
declare namespace Bowser {
/**
* Creates a Parser instance
* @param {string} UA - User agent string
* @param {boolean} skipParsing
*/
function getParser(UA: string, skipParsing?: boolean): Parser.Parser;
/**
* Creates a Parser instance and runs Parser.getResult immediately
* @param UA - User agent string
* @returns {Parser.ParsedResult}
*/
function parse(UA: string): Parser.ParsedResult;
/**
* Constants exposed via bowser getters
*/
const BROWSER_MAP: Record<string, string>;
const ENGINE_MAP: Record<string, string>;
const OS_MAP: Record<string, string>;
const PLATFORMS_MAP: Record<string, string>;
namespace Parser {
interface Parser {
constructor(UA: string, skipParsing?: boolean): Parser.Parser;
/**
* Check if the version is equals the browser version
* @param version The string to compare with the browser version
* @returns {boolean}
*/
compareVersion(version: string): boolean;
/**
* Get parsed browser object
* @return {BrowserDetails} Browser's details
*/
getBrowser(): BrowserDetails;
/**
* Get browser's name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} Browser's name or an empty string
*/
getBrowserName(toLowerCase?: boolean): string;
/**
* Get browser's version
* @return {String} version of browser
*/
getBrowserVersion(): string | undefined;
/**
* Get OS
* @return {OSDetails} - OS Details
*
* @example
* this.getOS(); // {
* // name: 'macOS',
* // version: '10.11.12',
* // }
*/
getOS(): OSDetails;
/**
* Get OS name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} name of the OS macOS, Windows, Linux, etc.
*/
getOSName(toLowerCase?: boolean): string;
/**
* Get OS version
* @return {String} full version with dots ('10.11.12', '5.6', etc)
*/
getOSVersion(): string;
/**
* Get parsed platform
* @returns {PlatformDetails}
*/
getPlatform(): PlatformDetails;
/**
* Get platform name
* @param {boolean} toLowerCase
*/
getPlatformType(toLowerCase?: boolean): string;
/**
* Get parsed engine
* @returns {EngineDetails}
*/
getEngine(): EngineDetails;
/**
* Get parsed engine's name
* @returns {String} Engine's name or an empty string
*/
getEngineName(): string;
/**
* Get parsed result
* @return {ParsedResult}
*/
getResult(): ParsedResult;
/**
* Get UserAgent string of current Parser instance
* @return {String} User-Agent String of the current <Parser> object
*/
getUA(): string;
/**
* Is anything? Check if the browser is called "anything",
* the OS called "anything" or the platform called "anything"
* @param {String} anything
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {Boolean}
*/
is(anything: any, includingAlias?: boolean): boolean;
/**
* Check if the browser name equals the passed string
* @param browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName: string, includingAlias?: boolean): boolean;
/**
* Check if the engine name equals the passed string
* @param engineName The string to compare with the engine name
* @returns {boolean}
*/
isEngine(engineName: string): boolean;
/**
* Check if the OS name equals the passed string
* @param OSName The string to compare with the OS name
* @returns {boolean}
*/
isOS(OSName: string): boolean;
/**
* Check if the platform name equals the passed string
* @param platformName The string to compare with the platform name
* @returns {boolean}
*/
isPlatform(platformName: string): boolean;
/**
* Parse full information about the browser
* @returns {Parser.Parser}
*/
parse(): Parser.Parser;
/**
* Get parsed browser object
* @returns {BrowserDetails}
*/
parseBrowser(): BrowserDetails;
/**
* Get parsed engine
* @returns {EngineDetails}
*/
parseEngine(): EngineDetails;
/**
* Parse OS and save it to this.parsedResult.os
* @returns {OSDetails}
*/
parseOS(): OSDetails;
/**
* Get parsed platform
* @returns {PlatformDetails}
*/
parsePlatform(): PlatformDetails;
/**
* Check if parsed browser matches certain conditions
*
* @param {checkTree} checkTree It's one or two layered object,
* which can include a platform or an OS on the first layer
* and should have browsers specs on the bottom-laying layer
*
* @returns {Boolean|undefined} Whether the browser satisfies the set conditions or not.
* Returns `undefined` when the browser is no described in the checkTree object.
*
* @example
* const browser = new Bowser(UA);
* if (browser.check({chrome: '>118.01.1322' }))
* // or with os
* if (browser.check({windows: { chrome: '>118.01.1322' } }))
* // or with platforms
* if (browser.check({desktop: { chrome: '>118.01.1322' } }))
*/
satisfies(checkTree: checkTree): boolean | undefined;
/**
* Check if the browser name equals the passed string
* @param {string} browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName: string, includingAlias?: boolean): boolean;
/**
* Check if the engine name equals the passed string
* @param {string} engineName The string to compare with the engine name
* @returns {boolean}
*/
isEngine(engineName: string): boolean;
/**
* Check if the platform type equals the passed string
* @param {string} platformType The string to compare with the platform type
* @returns {boolean}
*/
isPlatform(platformType: string): boolean;
/**
* Check if the OS name equals the passed string
* @param {string} osName The string to compare with the OS name
* @returns {boolean}
*/
isOS(osName: string): boolean;
/**
* Check if any of the given values satisfies `.is(anything)`
* @param {string[]} anythings
* @returns {boolean} true if at least one condition is satisfied, false otherwise.
*/
some(anythings: string[]): boolean | undefined;
/**
* Test a UA string for a regexp
* @param regex
* @returns {boolean} true if the regex matches the UA, false otherwise.
*/
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 {
[key: string]: any;
}
}
}

24
jsdoc.json Normal file
View File

@ -0,0 +1,24 @@
{
"tags": {
"allowUnknownTags": true
},
"source": {
"include": ["src", "README.md"],
"includePattern": ".js$",
"excludePattern": "(node_modules/|docs)"
},
"plugins": [
"plugins/markdown"
],
"opts": {
"template": "node_modules/docdash",
"encoding": "utf8",
"destination": "docs/",
"recurse": true,
"verbose": true
},
"templates": {
"cleverLinks": false,
"monospaceLinks": false
}
}

View File

@ -1,24 +0,0 @@
require('smoosh').config({
"JAVASCRIPT": {
"DIST_DIR": "./"
, "bowser": [
"./src/bowser.js"
]
}
, "JSHINT_OPTS": {
"boss": true
, "forin": false
, "curly": false
, "debug": false
, "devel": false
, "evil": false
, "regexp": false
, "undef": false
, "sub": true
, "white": false
, "indent": 2
, "asi": true
, "laxbreak": true
, "laxcomma": true
}
}).run().build().analyze()

14506
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
{
"name": "bowser",
"version": "1.9.2",
"description": "Lightweight browser detector",
"keywords": [
"browser",
@ -14,25 +13,71 @@
],
"homepage": "https://github.com/lancedikson/bowser",
"author": "Dustin Diaz <dustin@dustindiaz.com> (http://dustindiaz.com)",
"main": "./src/bowser.js",
"typings": "./typings.d.ts",
"contributors": [
{
"name": "Denis Demchenko",
"url": "http://twitter.com/lancedikson"
}
],
"main": "es5.js",
"browser": "es5.js",
"module": "src/bowser.js",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/ded/bowser.git"
"url": "git+https://github.com/lancedikson/bowser.git"
},
"devDependencies": {
"smoosh": "*",
"mocha": "*"
"@babel/cli": "^7.11.6",
"@babel/core": "^7.8.0",
"@babel/polyfill": "^7.8.3",
"@babel/preset-env": "^7.8.2",
"@babel/register": "^7.8.3",
"ava": "^3.0.0",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-istanbul": "^6.0.0",
"compression-webpack-plugin": "^4.0.0",
"coveralls": "^3.0.6",
"docdash": "^1.1.1",
"eslint": "^6.5.1",
"eslint-config-airbnb-base": "^13.2.0",
"eslint-plugin-ava": "^10.0.0",
"eslint-plugin-import": "^2.18.2",
"gh-pages": "^3.0.0",
"jsdoc": "^3.6.3",
"nyc": "^15.0.0",
"sinon": "^9.0.0",
"testem": "^3.0.0",
"webpack": "^4.41.0",
"webpack-bundle-analyzer": "^3.5.2",
"webpack-cli": "^3.3.9",
"yamljs": "^0.3.0"
},
"ava": {
"require": [
"@babel/register"
]
},
"bugs": {
"url": "https://github.com/ded/bowser/issues"
"url": "https://github.com/lancedikson/bowser/issues"
},
"directories": {
"test": "test"
},
"scripts": {
"test": "make test",
"prepublish": "make boosh"
"build": "webpack --config webpack.config.js",
"generate-and-deploy-docs": "npm run generate-docs && gh-pages --dist docs --dest docs",
"watch": "webpack --watch --config webpack.config.js",
"prepublishOnly": "npm run build",
"lint:check": "eslint ./src",
"lint:fix": "eslint --fix ./src",
"testem": "testem",
"test": "nyc --reporter=html --reporter=text ava",
"test:watch": "ava --watch",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"generate-docs": "jsdoc -c jsdoc.json"
},
"license": "MIT"
}

View File

@ -1,620 +1,77 @@
/*!
* Bowser - a browser detector
* https://github.com/ded/bowser
* MIT License | (c) Dustin Diaz 2015
* https://github.com/lancedikson/bowser
* MIT License | (c) Dustin Diaz 2012-2015
* MIT License | (c) Denis Demchenko 2015-2019
*/
import Parser from './parser.js';
import {
BROWSER_MAP,
ENGINE_MAP,
OS_MAP,
PLATFORMS_MAP,
} from './constants.js';
!function (root, name, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(name, definition)
else root[name] = definition()
}(this, 'bowser', function () {
/**
* Bowser class.
* Keep it simple as much as it can be.
* It's supposed to work with collections of {@link Parser} instances
* rather then solve one-instance problems.
* All the one-instance stuff is located in Parser class.
*
* @class
* @classdesc Bowser is a static object, that provides an API to the Parsers
* @hideconstructor
*/
class Bowser {
/**
* See useragents.js for examples of navigator.userAgent
*/
var t = true
function detect(ua) {
function getFirstMatch(regex) {
var match = ua.match(regex);
return (match && match.length > 1 && match[1]) || '';
}
function getSecondMatch(regex) {
var match = ua.match(regex);
return (match && match.length > 1 && match[2]) || '';
}
var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase()
, likeAndroid = /like android/i.test(ua)
, android = !likeAndroid && /android/i.test(ua)
, nexusMobile = /nexus\s*[0-6]\s*/i.test(ua)
, nexusTablet = !nexusMobile && /nexus\s*[0-9]+/i.test(ua)
, chromeos = /CrOS/.test(ua)
, silk = /silk/i.test(ua)
, sailfish = /sailfish/i.test(ua)
, tizen = /tizen/i.test(ua)
, webos = /(web|hpw)os/i.test(ua)
, windowsphone = /windows phone/i.test(ua)
, samsungBrowser = /SamsungBrowser/i.test(ua)
, windows = !windowsphone && /windows/i.test(ua)
, mac = !iosdevice && !silk && /macintosh/i.test(ua)
, linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua)
, edgeVersion = getSecondMatch(/edg([ea]|ios)\/(\d+(\.\d+)?)/i)
, versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i)
, tablet = /tablet/i.test(ua) && !/tablet pc/i.test(ua)
, mobile = !tablet && /[^-]mobi/i.test(ua)
, xbox = /xbox/i.test(ua)
, result
if (/opera/i.test(ua)) {
// an old Opera
result = {
name: 'Opera'
, opera: t
, version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i)
}
} else if (/opr\/|opios/i.test(ua)) {
// a new Opera
result = {
name: 'Opera'
, opera: t
, version: getFirstMatch(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i) || versionIdentifier
}
}
else if (/SamsungBrowser/i.test(ua)) {
result = {
name: 'Samsung Internet for Android'
, samsungBrowser: t
, version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i)
}
}
else if (/coast/i.test(ua)) {
result = {
name: 'Opera Coast'
, coast: t
, version: versionIdentifier || getFirstMatch(/(?:coast)[\s\/](\d+(\.\d+)?)/i)
}
}
else if (/yabrowser/i.test(ua)) {
result = {
name: 'Yandex Browser'
, yandexbrowser: t
, version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i)
}
}
else if (/ucbrowser/i.test(ua)) {
result = {
name: 'UC Browser'
, ucbrowser: t
, version: getFirstMatch(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i)
}
}
else if (/mxios/i.test(ua)) {
result = {
name: 'Maxthon'
, maxthon: t
, version: getFirstMatch(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i)
}
}
else if (/epiphany/i.test(ua)) {
result = {
name: 'Epiphany'
, epiphany: t
, version: getFirstMatch(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i)
}
}
else if (/puffin/i.test(ua)) {
result = {
name: 'Puffin'
, puffin: t
, version: getFirstMatch(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i)
}
}
else if (/sleipnir/i.test(ua)) {
result = {
name: 'Sleipnir'
, sleipnir: t
, version: getFirstMatch(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i)
}
}
else if (/k-meleon/i.test(ua)) {
result = {
name: 'K-Meleon'
, kMeleon: t
, version: getFirstMatch(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i)
}
}
else if (windowsphone) {
result = {
name: 'Windows Phone'
, osname: 'Windows Phone'
, windowsphone: t
}
if (edgeVersion) {
result.msedge = t
result.version = edgeVersion
}
else {
result.msie = t
result.version = getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i)
}
}
else if (/msie|trident/i.test(ua)) {
result = {
name: 'Internet Explorer'
, msie: t
, version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i)
}
} else if (chromeos) {
result = {
name: 'Chrome'
, osname: 'Chrome OS'
, chromeos: t
, chromeBook: t
, chrome: t
, version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)
}
} else if (/edg([ea]|ios)/i.test(ua)) {
result = {
name: 'Microsoft Edge'
, msedge: t
, version: edgeVersion
}
}
else if (/vivaldi/i.test(ua)) {
result = {
name: 'Vivaldi'
, vivaldi: t
, version: getFirstMatch(/vivaldi\/(\d+(\.\d+)?)/i) || versionIdentifier
}
}
else if (sailfish) {
result = {
name: 'Sailfish'
, osname: 'Sailfish OS'
, sailfish: t
, version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i)
}
}
else if (/seamonkey\//i.test(ua)) {
result = {
name: 'SeaMonkey'
, seamonkey: t
, version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i)
}
}
else if (/firefox|iceweasel|fxios/i.test(ua)) {
result = {
name: 'Firefox'
, firefox: t
, version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i)
}
if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) {
result.firefoxos = t
result.osname = 'Firefox OS'
}
}
else if (silk) {
result = {
name: 'Amazon Silk'
, silk: t
, version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i)
}
}
else if (/phantom/i.test(ua)) {
result = {
name: 'PhantomJS'
, phantom: t
, version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i)
}
}
else if (/slimerjs/i.test(ua)) {
result = {
name: 'SlimerJS'
, slimer: t
, version: getFirstMatch(/slimerjs\/(\d+(\.\d+)?)/i)
}
}
else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) {
result = {
name: 'BlackBerry'
, osname: 'BlackBerry OS'
, blackberry: t
, version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i)
}
}
else if (webos) {
result = {
name: 'WebOS'
, osname: 'WebOS'
, webos: t
, version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i)
};
/touchpad\//i.test(ua) && (result.touchpad = t)
}
else if (/bada/i.test(ua)) {
result = {
name: 'Bada'
, osname: 'Bada'
, bada: t
, version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i)
};
}
else if (tizen) {
result = {
name: 'Tizen'
, osname: 'Tizen'
, tizen: t
, version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier
};
}
else if (/qupzilla/i.test(ua)) {
result = {
name: 'QupZilla'
, qupzilla: t
, version: getFirstMatch(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i) || versionIdentifier
}
}
else if (/chromium/i.test(ua)) {
result = {
name: 'Chromium'
, chromium: t
, version: getFirstMatch(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i) || versionIdentifier
}
}
else if (/chrome|crios|crmo/i.test(ua)) {
result = {
name: 'Chrome'
, chrome: t
, version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)
}
}
else if (android) {
result = {
name: 'Android'
, version: versionIdentifier
}
}
else if (/safari|applewebkit/i.test(ua)) {
result = {
name: 'Safari'
, safari: t
}
if (versionIdentifier) {
result.version = versionIdentifier
}
}
else if (iosdevice) {
result = {
name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod'
}
// WTF: version is not part of user agent in web apps
if (versionIdentifier) {
result.version = versionIdentifier
}
}
else if(/googlebot/i.test(ua)) {
result = {
name: 'Googlebot'
, googlebot: t
, version: getFirstMatch(/googlebot\/(\d+(\.\d+))/i) || versionIdentifier
}
}
else {
result = {
name: getFirstMatch(/^(.*)\/(.*) /),
version: getSecondMatch(/^(.*)\/(.*) /)
};
}
// set webkit or gecko flag for browsers based on these engines
if (!result.msedge && /(apple)?webkit/i.test(ua)) {
if (/(apple)?webkit\/537\.36/i.test(ua)) {
result.name = result.name || "Blink"
result.blink = t
} else {
result.name = result.name || "Webkit"
result.webkit = t
}
if (!result.version && versionIdentifier) {
result.version = versionIdentifier
}
} else if (!result.opera && /gecko\//i.test(ua)) {
result.name = result.name || "Gecko"
result.gecko = t
result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i)
}
// set OS flags for platforms that have multiple browsers
if (!result.windowsphone && (android || result.silk)) {
result.android = t
result.osname = 'Android'
} else if (!result.windowsphone && iosdevice) {
result[iosdevice] = t
result.ios = t
result.osname = 'iOS'
} else if (mac) {
result.mac = t
result.osname = 'macOS'
} else if (xbox) {
result.xbox = t
result.osname = 'Xbox'
} else if (windows) {
result.windows = t
result.osname = 'Windows'
} else if (linux) {
result.linux = t
result.osname = 'Linux'
}
function getWindowsVersion (s) {
switch (s) {
case 'NT': return 'NT'
case 'XP': return 'XP'
case 'NT 5.0': return '2000'
case 'NT 5.1': return 'XP'
case 'NT 5.2': return '2003'
case 'NT 6.0': return 'Vista'
case 'NT 6.1': return '7'
case 'NT 6.2': return '8'
case 'NT 6.3': return '8.1'
case 'NT 10.0': return '10'
default: return undefined
}
}
// OS version extraction
var osVersion = '';
if (result.windows) {
osVersion = getWindowsVersion(getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i))
} else if (result.windowsphone) {
osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i);
} else if (result.mac) {
osVersion = getFirstMatch(/Mac OS X (\d+([_\.\s]\d+)*)/i);
osVersion = osVersion.replace(/[_\s]/g, '.');
} else if (iosdevice) {
osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i);
osVersion = osVersion.replace(/[_\s]/g, '.');
} else if (android) {
osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i);
} else if (result.webos) {
osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i);
} else if (result.blackberry) {
osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i);
} else if (result.bada) {
osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i);
} else if (result.tizen) {
osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i);
}
if (osVersion) {
result.osversion = osVersion;
}
// device type extraction
var osMajorVersion = !result.windows && osVersion.split('.')[0];
if (
tablet
|| nexusTablet
|| iosdevice == 'ipad'
|| (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile)))
|| result.silk
) {
result.tablet = t
} else if (
mobile
|| iosdevice == 'iphone'
|| iosdevice == 'ipod'
|| android
|| nexusMobile
|| result.blackberry
|| result.webos
|| result.bada
) {
result.mobile = t
}
// Graded Browser Support
// http://developer.yahoo.com/yui/articles/gbs
if (result.msedge ||
(result.msie && result.version >= 10) ||
(result.yandexbrowser && result.version >= 15) ||
(result.vivaldi && result.version >= 1.0) ||
(result.chrome && result.version >= 20) ||
(result.samsungBrowser && result.version >= 4) ||
(result.firefox && result.version >= 20.0) ||
(result.safari && result.version >= 6) ||
(result.opera && result.version >= 10.0) ||
(result.ios && result.osversion && result.osversion.split(".")[0] >= 6) ||
(result.blackberry && result.version >= 10.1)
|| (result.chromium && result.version >= 20)
) {
result.a = t;
}
else if ((result.msie && result.version < 10) ||
(result.chrome && result.version < 20) ||
(result.firefox && result.version < 20.0) ||
(result.safari && result.version < 6) ||
(result.opera && result.version < 10.0) ||
(result.ios && result.osversion && result.osversion.split(".")[0] < 6)
|| (result.chromium && result.version < 20)
) {
result.c = t
} else result.x = t
return result
}
var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '')
bowser.test = function (browserList) {
for (var i = 0; i < browserList.length; ++i) {
var browserItem = browserList[i];
if (typeof browserItem=== 'string') {
if (browserItem in bowser) {
return true;
}
}
}
return false;
}
/**
* Get version precisions count
* Creates a {@link Parser} instance
*
* @param {String} UA UserAgent string
* @param {Boolean} [skipParsing=false] Will make the Parser postpone parsing until you ask it
* explicitly. Same as `skipParsing` for {@link Parser}.
* @returns {Parser}
* @throws {Error} when UA is not a String
*
* @example
* getVersionPrecision("1.10.3") // 3
*
* @param {string} version
* @return {number}
* const parser = Bowser.getParser(window.navigator.userAgent);
* const result = parser.getResult();
*/
function getVersionPrecision(version) {
return version.split(".").length;
static getParser(UA, skipParsing = false) {
if (typeof UA !== 'string') {
throw new Error('UserAgent should be a string');
}
return new Parser(UA, skipParsing);
}
/**
* Array::map polyfill
* Creates a {@link Parser} instance and runs {@link Parser.getResult} immediately
*
* @param {Array} arr
* @param {Function} iterator
* @return {Array}
*/
function map(arr, iterator) {
var result = [], i;
if (Array.prototype.map) {
return Array.prototype.map.call(arr, iterator);
}
for (i = 0; i < arr.length; i++) {
result.push(iterator(arr[i]));
}
return result;
}
/**
* Calculate browser version weight
* @param UA
* @return {ParsedResult}
*
* @example
* compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1
* compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1
* compareVersions(['1.10.2.1', '1.10.2.1']); // 0
* compareVersions(['1.10.2.1', '1.0800.2']); // -1
*
* @param {Array<String>} versions versions to compare
* @return {Number} comparison result
* const result = Bowser.parse(window.navigator.userAgent);
*/
function compareVersions(versions) {
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1]));
var chunks = map(versions, function (version) {
var delta = precision - getVersionPrecision(version);
// 2) "9" -> "9.0" (for precision = 2)
version = version + new Array(delta + 1).join(".0");
// 3) "9.0" -> ["000000000"", "000000009"]
return map(version.split("."), function (chunk) {
return new Array(20 - chunk.length).join("0") + chunk;
}).reverse();
});
// iterate in reverse order by reversed chunks array
while (--precision >= 0) {
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
if (chunks[0][precision] > chunks[1][precision]) {
return 1;
}
else if (chunks[0][precision] === chunks[1][precision]) {
if (precision === 0) {
// all version chunks are same
return 0;
}
}
else {
return -1;
}
}
static parse(UA) {
return (new Parser(UA)).getResult();
}
/**
* Check if browser is unsupported
*
* @example
* bowser.isUnsupportedBrowser({
* msie: "10",
* firefox: "23",
* chrome: "29",
* safari: "5.1",
* opera: "16",
* phantom: "534"
* });
*
* @param {Object} minVersions map of minimal version to browser
* @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map
* @param {String} [ua] user agent string
* @return {Boolean}
*/
function isUnsupportedBrowser(minVersions, strictMode, ua) {
var _bowser = bowser;
// make strictMode param optional with ua param usage
if (typeof strictMode === 'string') {
ua = strictMode;
strictMode = void(0);
}
if (strictMode === void(0)) {
strictMode = false;
}
if (ua) {
_bowser = detect(ua);
}
var version = "" + _bowser.version;
for (var browser in minVersions) {
if (minVersions.hasOwnProperty(browser)) {
if (_bowser[browser]) {
if (typeof minVersions[browser] !== 'string') {
throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions));
}
// browser version and min supported version.
return compareVersions([version, minVersions[browser]]) < 0;
}
}
}
return strictMode; // not found
static get BROWSER_MAP() {
return BROWSER_MAP;
}
/**
* Check if browser is supported
*
* @param {Object} minVersions map of minimal version to browser
* @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map
* @param {String} [ua] user agent string
* @return {Boolean}
*/
function check(minVersions, strictMode, ua) {
return !isUnsupportedBrowser(minVersions, strictMode, ua);
static get ENGINE_MAP() {
return ENGINE_MAP;
}
bowser.isUnsupportedBrowser = isUnsupportedBrowser;
bowser.compareVersions = compareVersions;
bowser.check = check;
static get OS_MAP() {
return OS_MAP;
}
/*
* Set our detect method to the main bowser object so we can
* reuse it to test other user agents.
* This is needed to implement future tests.
*/
bowser._detect = detect;
static get PLATFORMS_MAP() {
return PLATFORMS_MAP;
}
}
/*
* Set our detect public method to the main bowser object
* This is needed to implement bowser in server side
*/
bowser.detect = detect;
return bowser
});
export default Bowser;

119
src/constants.js Normal file
View File

@ -0,0 +1,119 @@
// NOTE: this list must be up-to-date with browsers listed in
// test/acceptance/useragentstrings.yml
export const BROWSER_ALIASES_MAP = {
'Amazon Silk': 'amazon_silk',
'Android Browser': 'android',
Bada: 'bada',
BlackBerry: 'blackberry',
Chrome: 'chrome',
Chromium: 'chromium',
Electron: 'electron',
Epiphany: 'epiphany',
Firefox: 'firefox',
Focus: 'focus',
Generic: 'generic',
'Google Search': 'google_search',
Googlebot: 'googlebot',
'Internet Explorer': 'ie',
'K-Meleon': 'k_meleon',
Maxthon: 'maxthon',
'Microsoft Edge': 'edge',
'MZ Browser': 'mz',
'NAVER Whale Browser': 'naver',
Opera: 'opera',
'Opera Coast': 'opera_coast',
'Pale Moon': 'pale_moon',
PhantomJS: 'phantomjs',
Puffin: 'puffin',
QupZilla: 'qupzilla',
QQ: 'qq',
QQLite: 'qqlite',
Safari: 'safari',
Sailfish: 'sailfish',
'Samsung Internet for Android': 'samsung_internet',
SeaMonkey: 'seamonkey',
Sleipnir: 'sleipnir',
Swing: 'swing',
Tizen: 'tizen',
'UC Browser': 'uc',
Vivaldi: 'vivaldi',
'WebOS Browser': 'webos',
WeChat: 'wechat',
'Yandex Browser': 'yandex',
Roku: 'roku',
};
export const BROWSER_MAP = {
amazon_silk: 'Amazon Silk',
android: 'Android Browser',
bada: 'Bada',
blackberry: 'BlackBerry',
chrome: 'Chrome',
chromium: 'Chromium',
electron: 'Electron',
epiphany: 'Epiphany',
firefox: 'Firefox',
focus: 'Focus',
generic: 'Generic',
googlebot: 'Googlebot',
google_search: 'Google Search',
ie: 'Internet Explorer',
k_meleon: 'K-Meleon',
maxthon: 'Maxthon',
edge: 'Microsoft Edge',
mz: 'MZ Browser',
naver: 'NAVER Whale Browser',
opera: 'Opera',
opera_coast: 'Opera Coast',
pale_moon: 'Pale Moon',
phantomjs: 'PhantomJS',
puffin: 'Puffin',
qupzilla: 'QupZilla',
qq: 'QQ Browser',
qqlite: 'QQ Browser Lite',
safari: 'Safari',
sailfish: 'Sailfish',
samsung_internet: 'Samsung Internet for Android',
seamonkey: 'SeaMonkey',
sleipnir: 'Sleipnir',
swing: 'Swing',
tizen: 'Tizen',
uc: 'UC Browser',
vivaldi: 'Vivaldi',
webos: 'WebOS Browser',
wechat: 'WeChat',
yandex: 'Yandex Browser',
};
export const PLATFORMS_MAP = {
tablet: 'tablet',
mobile: 'mobile',
desktop: 'desktop',
tv: 'tv',
bot: 'bot',
};
export const OS_MAP = {
WindowsPhone: 'Windows Phone',
Windows: 'Windows',
MacOS: 'macOS',
iOS: 'iOS',
Android: 'Android',
WebOS: 'WebOS',
BlackBerry: 'BlackBerry',
Bada: 'Bada',
Tizen: 'Tizen',
Linux: 'Linux',
ChromeOS: 'Chrome OS',
PlayStation4: 'PlayStation 4',
Roku: 'Roku',
};
export const ENGINE_MAP = {
EdgeHTML: 'EdgeHTML',
Blink: 'Blink',
Trident: 'Trident',
Presto: 'Presto',
Gecko: 'Gecko',
WebKit: 'WebKit',
};

715
src/parser-browsers.js Normal file
View File

@ -0,0 +1,715 @@
/**
* Browsers' descriptors
*
* The idea of descriptors is simple. You should know about them two simple things:
* 1. Every descriptor has a method or property called `test` and a `describe` method.
* 2. Order of descriptors is important.
*
* More details:
* 1. Method or property `test` serves as a way to detect whether the UA string
* matches some certain browser or not. The `describe` method helps to make a result
* object with params that show some browser-specific things: name, version, etc.
* 2. Order of descriptors is important because a Parser goes through them one by one
* in course. For example, if you insert Chrome's descriptor as the first one,
* more then a half of browsers will be described as Chrome, because they will pass
* the Chrome descriptor's test.
*
* Descriptor's `test` could be a property with an array of RegExps, where every RegExp
* will be applied to a UA string to test it whether it matches or not.
* If a descriptor has two or more regexps in the `test` array it tests them one by one
* with a logical sum operation. Parser stops if it has found any RegExp that matches the UA.
*
* Or `test` could be a method. In that case it gets a Parser instance and should
* return true/false to get the Parser know if this browser descriptor matches the UA or not.
*/
import Utils from './utils.js';
const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
const browsersList = [
/* Googlebot */
{
test: [/googlebot/i],
describe(ua) {
const browser = {
name: 'Googlebot',
};
const version = Utils.getFirstMatch(/googlebot\/(\d+(\.\d+))/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
/* Opera < 13.0 */
{
test: [/opera/i],
describe(ua) {
const browser = {
name: 'Opera',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
/* Opera > 13.0 */
{
test: [/opr\/|opios/i],
describe(ua) {
const browser = {
name: 'Opera',
};
const version = Utils.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/SamsungBrowser/i],
describe(ua) {
const browser = {
name: 'Samsung Internet for Android',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/Whale/i],
describe(ua) {
const browser = {
name: 'NAVER Whale Browser',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/PaleMoon/i],
describe(ua) {
const browser = {
name: 'Pale Moon',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:PaleMoon)[\s/](\d+(?:\.\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/MZBrowser/i],
describe(ua) {
const browser = {
name: 'MZ Browser',
};
const version = Utils.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/focus/i],
describe(ua) {
const browser = {
name: 'Focus',
};
const version = Utils.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/swing/i],
describe(ua) {
const browser = {
name: 'Swing',
};
const version = Utils.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/coast/i],
describe(ua) {
const browser = {
name: 'Opera Coast',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/opt\/\d+(?:.?_?\d+)+/i],
describe(ua) {
const browser = {
name: 'Opera Touch',
};
const version = Utils.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/yabrowser/i],
describe(ua) {
const browser = {
name: 'Yandex Browser',
};
const version = Utils.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/ucbrowser/i],
describe(ua) {
const browser = {
name: 'UC Browser',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/Maxthon|mxios/i],
describe(ua) {
const browser = {
name: 'Maxthon',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/epiphany/i],
describe(ua) {
const browser = {
name: 'Epiphany',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/puffin/i],
describe(ua) {
const browser = {
name: 'Puffin',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/sleipnir/i],
describe(ua) {
const browser = {
name: 'Sleipnir',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/k-meleon/i],
describe(ua) {
const browser = {
name: 'K-Meleon',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/micromessenger/i],
describe(ua) {
const browser = {
name: 'WeChat',
};
const version = Utils.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/qqbrowser/i],
describe(ua) {
const browser = {
name: (/qqbrowserlite/i).test(ua) ? 'QQ Browser Lite' : 'QQ Browser',
};
const version = Utils.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/msie|trident/i],
describe(ua) {
const browser = {
name: 'Internet Explorer',
};
const version = Utils.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/\sedg\//i],
describe(ua) {
const browser = {
name: 'Microsoft Edge',
};
const version = Utils.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/edg([ea]|ios)/i],
describe(ua) {
const browser = {
name: 'Microsoft Edge',
};
const version = Utils.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/vivaldi/i],
describe(ua) {
const browser = {
name: 'Vivaldi',
};
const version = Utils.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/seamonkey/i],
describe(ua) {
const browser = {
name: 'SeaMonkey',
};
const version = Utils.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/sailfish/i],
describe(ua) {
const browser = {
name: 'Sailfish',
};
const version = Utils.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/silk/i],
describe(ua) {
const browser = {
name: 'Amazon Silk',
};
const version = Utils.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/phantom/i],
describe(ua) {
const browser = {
name: 'PhantomJS',
};
const version = Utils.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/slimerjs/i],
describe(ua) {
const browser = {
name: 'SlimerJS',
};
const version = Utils.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
describe(ua) {
const browser = {
name: 'BlackBerry',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/(web|hpw)[o0]s/i],
describe(ua) {
const browser = {
name: 'WebOS Browser',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/bada/i],
describe(ua) {
const browser = {
name: 'Bada',
};
const version = Utils.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/tizen/i],
describe(ua) {
const browser = {
name: 'Tizen',
};
const version = Utils.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/qupzilla/i],
describe(ua) {
const browser = {
name: 'QupZilla',
};
const version = Utils.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/firefox|iceweasel|fxios/i],
describe(ua) {
const browser = {
name: 'Firefox',
};
const version = Utils.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/electron/i],
describe(ua) {
const browser = {
name: 'Electron',
};
const version = Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/MiuiBrowser/i],
describe(ua) {
const browser = {
name: 'Miui',
};
const version = Utils.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/chromium/i],
describe(ua) {
const browser = {
name: 'Chromium',
};
const version = Utils.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/chrome|crios|crmo/i],
describe(ua) {
const browser = {
name: 'Chrome',
};
const version = Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
{
test: [/GSA/i],
describe(ua) {
const browser = {
name: 'Google Search',
};
const version = Utils.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
/* Android Browser */
{
test(parser) {
const notLikeAndroid = !parser.test(/like android/i);
const butAndroid = parser.test(/android/i);
return notLikeAndroid && butAndroid;
},
describe(ua) {
const browser = {
name: 'Android Browser',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
/* PlayStation 4 */
{
test: [/playstation 4/i],
describe(ua) {
const browser = {
name: 'PlayStation 4',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
/* Safari */
{
test: [/safari|applewebkit/i],
describe(ua) {
const browser = {
name: 'Safari',
};
const version = Utils.getFirstMatch(commonVersionIdentifier, ua);
if (version) {
browser.version = version;
}
return browser;
},
},
/* Something else */
{
test: [/.*/i],
describe(ua) {
/* Here we try to make sure that there are explicit details about the device
* in order to decide what regexp exactly we want to apply
* (as there is a specific decision based on that conclusion)
*/
const regexpWithoutDeviceSpec = /^(.*)\/(.*) /;
const regexpWithDeviceSpec = /^(.*)\/(.*)[ \t]\((.*)/;
const hasDeviceSpec = ua.search('\\(') !== -1;
const regexp = hasDeviceSpec ? regexpWithDeviceSpec : regexpWithoutDeviceSpec;
return {
name: Utils.getFirstMatch(regexp, ua),
version: Utils.getSecondMatch(regexp, ua),
};
},
},
];
export default browsersList;

120
src/parser-engines.js Normal file
View File

@ -0,0 +1,120 @@
import Utils from './utils.js';
import { ENGINE_MAP } from './constants.js';
/*
* More specific goes first
*/
export default [
/* EdgeHTML */
{
test(parser) {
return parser.getBrowserName(true) === 'microsoft edge';
},
describe(ua) {
const isBlinkBased = /\sedg\//i.test(ua);
// return blink if it's blink-based one
if (isBlinkBased) {
return {
name: ENGINE_MAP.Blink,
};
}
// otherwise match the version and return EdgeHTML
const version = Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i, ua);
return {
name: ENGINE_MAP.EdgeHTML,
version,
};
},
},
/* Trident */
{
test: [/trident/i],
describe(ua) {
const engine = {
name: ENGINE_MAP.Trident,
};
const version = Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
/* Presto */
{
test(parser) {
return parser.test(/presto/i);
},
describe(ua) {
const engine = {
name: ENGINE_MAP.Presto,
};
const version = Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
/* Gecko */
{
test(parser) {
const isGecko = parser.test(/gecko/i);
const likeGecko = parser.test(/like gecko/i);
return isGecko && !likeGecko;
},
describe(ua) {
const engine = {
name: ENGINE_MAP.Gecko,
};
const version = Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
/* Blink */
{
test: [/(apple)?webkit\/537\.36/i],
describe() {
return {
name: ENGINE_MAP.Blink,
};
},
},
/* WebKit */
{
test: [/(apple)?webkit/i],
describe(ua) {
const engine = {
name: ENGINE_MAP.WebKit,
};
const version = Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i, ua);
if (version) {
engine.version = version;
}
return engine;
},
},
];

199
src/parser-os.js Normal file
View File

@ -0,0 +1,199 @@
import Utils from './utils.js';
import { OS_MAP } from './constants.js';
export default [
/* Roku */
{
test: [/Roku\/DVP/],
describe(ua) {
const version = Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i, ua);
return {
name: OS_MAP.Roku,
version,
};
},
},
/* Windows Phone */
{
test: [/windows phone/i],
describe(ua) {
const version = Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.WindowsPhone,
version,
};
},
},
/* Windows */
{
test: [/windows /i],
describe(ua) {
const version = Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i, ua);
const versionName = Utils.getWindowsVersionName(version);
return {
name: OS_MAP.Windows,
version,
versionName,
};
},
},
/* Firefox on iPad */
{
test: [/Macintosh(.*?) FxiOS(.*?)\//],
describe(ua) {
const result = {
name: OS_MAP.iOS,
};
const version = Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/, ua);
if (version) {
result.version = version;
}
return result;
},
},
/* macOS */
{
test: [/macintosh/i],
describe(ua) {
const version = Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i, ua).replace(/[_\s]/g, '.');
const versionName = Utils.getMacOSVersionName(version);
const os = {
name: OS_MAP.MacOS,
version,
};
if (versionName) {
os.versionName = versionName;
}
return os;
},
},
/* iOS */
{
test: [/(ipod|iphone|ipad)/i],
describe(ua) {
const version = Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i, ua).replace(/[_\s]/g, '.');
return {
name: OS_MAP.iOS,
version,
};
},
},
/* Android */
{
test(parser) {
const notLikeAndroid = !parser.test(/like android/i);
const butAndroid = parser.test(/android/i);
return notLikeAndroid && butAndroid;
},
describe(ua) {
const version = Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i, ua);
const versionName = Utils.getAndroidVersionName(version);
const os = {
name: OS_MAP.Android,
version,
};
if (versionName) {
os.versionName = versionName;
}
return os;
},
},
/* WebOS */
{
test: [/(web|hpw)[o0]s/i],
describe(ua) {
const version = Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i, ua);
const os = {
name: OS_MAP.WebOS,
};
if (version && version.length) {
os.version = version;
}
return os;
},
},
/* BlackBerry */
{
test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
describe(ua) {
const version = Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i, ua)
|| Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i, ua)
|| Utils.getFirstMatch(/\bbb(\d+)/i, ua);
return {
name: OS_MAP.BlackBerry,
version,
};
},
},
/* Bada */
{
test: [/bada/i],
describe(ua) {
const version = Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.Bada,
version,
};
},
},
/* Tizen */
{
test: [/tizen/i],
describe(ua) {
const version = Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.Tizen,
version,
};
},
},
/* Linux */
{
test: [/linux/i],
describe() {
return {
name: OS_MAP.Linux,
};
},
},
/* Chrome OS */
{
test: [/CrOS/],
describe() {
return {
name: OS_MAP.ChromeOS,
};
},
},
/* Playstation 4 */
{
test: [/PlayStation 4/],
describe(ua) {
const version = Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i, ua);
return {
name: OS_MAP.PlayStation4,
version,
};
},
},
];

282
src/parser-platforms.js Normal file
View File

@ -0,0 +1,282 @@
import Utils from './utils.js';
import { PLATFORMS_MAP } from './constants.js';
/*
* Tablets go first since usually they have more specific
* signs to detect.
*/
export default [
/* Googlebot */
{
test: [/googlebot/i],
describe() {
return {
type: PLATFORMS_MAP.bot,
vendor: 'Google',
};
},
},
/* Huawei */
{
test: [/huawei/i],
describe(ua) {
const model = Utils.getFirstMatch(/(can-l01)/i, ua) && 'Nova';
const platform = {
type: PLATFORMS_MAP.mobile,
vendor: 'Huawei',
};
if (model) {
platform.model = model;
}
return platform;
},
},
/* Nexus Tablet */
{
test: [/nexus\s*(?:7|8|9|10).*/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Nexus',
};
},
},
/* iPad */
{
test: [/ipad/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Apple',
model: 'iPad',
};
},
},
/* Firefox on iPad */
{
test: [/Macintosh(.*?) FxiOS(.*?)\//],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Apple',
model: 'iPad',
};
},
},
/* Amazon Kindle Fire */
{
test: [/kftt build/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Amazon',
model: 'Kindle Fire HD 7',
};
},
},
/* Another Amazon Tablet with Silk */
{
test: [/silk/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
vendor: 'Amazon',
};
},
},
/* Tablet */
{
test: [/tablet(?! pc)/i],
describe() {
return {
type: PLATFORMS_MAP.tablet,
};
},
},
/* iPod/iPhone */
{
test(parser) {
const iDevice = parser.test(/ipod|iphone/i);
const likeIDevice = parser.test(/like (ipod|iphone)/i);
return iDevice && !likeIDevice;
},
describe(ua) {
const model = Utils.getFirstMatch(/(ipod|iphone)/i, ua);
return {
type: PLATFORMS_MAP.mobile,
vendor: 'Apple',
model,
};
},
},
/* Nexus Mobile */
{
test: [/nexus\s*[0-6].*/i, /galaxy nexus/i],
describe() {
return {
type: PLATFORMS_MAP.mobile,
vendor: 'Nexus',
};
},
},
/* Nokia */
{
test: [/Nokia/i],
describe(ua) {
const model = Utils.getFirstMatch(/Nokia\s+([0-9]+(\.[0-9]+)?)/i, ua);
const platform = {
type: PLATFORMS_MAP.mobile,
vendor: 'Nokia',
};
if (model) {
platform.model = model;
}
return platform;
},
},
/* Mobile */
{
test: [/[^-]mobi/i],
describe() {
return {
type: PLATFORMS_MAP.mobile,
};
},
},
/* BlackBerry */
{
test(parser) {
return parser.getBrowserName(true) === 'blackberry';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
vendor: 'BlackBerry',
};
},
},
/* Bada */
{
test(parser) {
return parser.getBrowserName(true) === 'bada';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
};
},
},
/* Windows Phone */
{
test(parser) {
return parser.getBrowserName() === 'windows phone';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
vendor: 'Microsoft',
};
},
},
/* Android Tablet */
{
test(parser) {
const osMajorVersion = Number(String(parser.getOSVersion()).split('.')[0]);
return parser.getOSName(true) === 'android' && (osMajorVersion >= 3);
},
describe() {
return {
type: PLATFORMS_MAP.tablet,
};
},
},
/* Android Mobile */
{
test(parser) {
return parser.getOSName(true) === 'android';
},
describe() {
return {
type: PLATFORMS_MAP.mobile,
};
},
},
/* desktop */
{
test(parser) {
return parser.getOSName(true) === 'macos';
},
describe() {
return {
type: PLATFORMS_MAP.desktop,
vendor: 'Apple',
};
},
},
/* Windows */
{
test(parser) {
return parser.getOSName(true) === 'windows';
},
describe() {
return {
type: PLATFORMS_MAP.desktop,
};
},
},
/* Linux */
{
test(parser) {
return parser.getOSName(true) === 'linux';
},
describe() {
return {
type: PLATFORMS_MAP.desktop,
};
},
},
/* PlayStation 4 */
{
test(parser) {
return parser.getOSName(true) === 'playstation 4';
},
describe() {
return {
type: PLATFORMS_MAP.tv,
};
},
},
/* Roku */
{
test(parser) {
return parser.getOSName(true) === 'roku';
},
describe() {
return {
type: PLATFORMS_MAP.tv,
};
},
},
];

511
src/parser.js Normal file
View File

@ -0,0 +1,511 @@
import browserParsersList from './parser-browsers.js';
import osParsersList from './parser-os.js';
import platformParsersList from './parser-platforms.js';
import enginesParsersList from './parser-engines.js';
import Utils from './utils.js';
/**
* The main class that arranges the whole parsing process.
*/
class Parser {
/**
* Create instance of Parser
*
* @param {String} UA User-Agent string
* @param {Boolean} [skipParsing=false] parser can skip parsing in purpose of performance
* improvements if you need to make a more particular parsing
* like {@link Parser#parseBrowser} or {@link Parser#parsePlatform}
*
* @throw {Error} in case of empty UA String
*
* @constructor
*/
constructor(UA, skipParsing = false) {
if (UA === void (0) || UA === null || UA === '') {
throw new Error("UserAgent parameter can't be empty");
}
this._ua = UA;
/**
* @typedef ParsedResult
* @property {Object} browser
* @property {String|undefined} [browser.name]
* Browser name, like `"Chrome"` or `"Internet Explorer"`
* @property {String|undefined} [browser.version] Browser version as a String `"12.01.45334.10"`
* @property {Object} os
* @property {String|undefined} [os.name] OS name, like `"Windows"` or `"macOS"`
* @property {String|undefined} [os.version] OS version, like `"NT 5.1"` or `"10.11.1"`
* @property {String|undefined} [os.versionName] OS name, like `"XP"` or `"High Sierra"`
* @property {Object} platform
* @property {String|undefined} [platform.type]
* platform type, can be either `"desktop"`, `"tablet"` or `"mobile"`
* @property {String|undefined} [platform.vendor] Vendor of the device,
* like `"Apple"` or `"Samsung"`
* @property {String|undefined} [platform.model] Device model,
* like `"iPhone"` or `"Kindle Fire HD 7"`
* @property {Object} engine
* @property {String|undefined} [engine.name]
* Can be any of this: `WebKit`, `Blink`, `Gecko`, `Trident`, `Presto`, `EdgeHTML`
* @property {String|undefined} [engine.version] String version of the engine
*/
this.parsedResult = {};
if (skipParsing !== true) {
this.parse();
}
}
/**
* Get UserAgent string of current Parser instance
* @return {String} User-Agent String of the current <Parser> object
*
* @public
*/
getUA() {
return this._ua;
}
/**
* Test a UA string for a regexp
* @param {RegExp} regex
* @return {Boolean}
*/
test(regex) {
return regex.test(this._ua);
}
/**
* Get parsed browser object
* @return {Object}
*/
parseBrowser() {
this.parsedResult.browser = {};
const browserDescriptor = Utils.find(browserParsersList, (_browser) => {
if (typeof _browser.test === 'function') {
return _browser.test(this);
}
if (Array.isArray(_browser.test)) {
return _browser.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (browserDescriptor) {
this.parsedResult.browser = browserDescriptor.describe(this.getUA());
}
return this.parsedResult.browser;
}
/**
* Get parsed browser object
* @return {Object}
*
* @public
*/
getBrowser() {
if (this.parsedResult.browser) {
return this.parsedResult.browser;
}
return this.parseBrowser();
}
/**
* Get browser's name
* @return {String} Browser's name or an empty string
*
* @public
*/
getBrowserName(toLowerCase) {
if (toLowerCase) {
return String(this.getBrowser().name).toLowerCase() || '';
}
return this.getBrowser().name || '';
}
/**
* Get browser's version
* @return {String} version of browser
*
* @public
*/
getBrowserVersion() {
return this.getBrowser().version;
}
/**
* Get OS
* @return {Object}
*
* @example
* this.getOS();
* {
* name: 'macOS',
* version: '10.11.12'
* }
*/
getOS() {
if (this.parsedResult.os) {
return this.parsedResult.os;
}
return this.parseOS();
}
/**
* Parse OS and save it to this.parsedResult.os
* @return {*|{}}
*/
parseOS() {
this.parsedResult.os = {};
const os = Utils.find(osParsersList, (_os) => {
if (typeof _os.test === 'function') {
return _os.test(this);
}
if (Array.isArray(_os.test)) {
return _os.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (os) {
this.parsedResult.os = os.describe(this.getUA());
}
return this.parsedResult.os;
}
/**
* Get OS name
* @param {Boolean} [toLowerCase] return lower-cased value
* @return {String} name of the OS macOS, Windows, Linux, etc.
*/
getOSName(toLowerCase) {
const { name } = this.getOS();
if (toLowerCase) {
return String(name).toLowerCase() || '';
}
return name || '';
}
/**
* Get OS version
* @return {String} full version with dots ('10.11.12', '5.6', etc)
*/
getOSVersion() {
return this.getOS().version;
}
/**
* Get parsed platform
* @return {{}}
*/
getPlatform() {
if (this.parsedResult.platform) {
return this.parsedResult.platform;
}
return this.parsePlatform();
}
/**
* Get platform name
* @param {Boolean} [toLowerCase=false]
* @return {*}
*/
getPlatformType(toLowerCase = false) {
const { type } = this.getPlatform();
if (toLowerCase) {
return String(type).toLowerCase() || '';
}
return type || '';
}
/**
* Get parsed platform
* @return {{}}
*/
parsePlatform() {
this.parsedResult.platform = {};
const platform = Utils.find(platformParsersList, (_platform) => {
if (typeof _platform.test === 'function') {
return _platform.test(this);
}
if (Array.isArray(_platform.test)) {
return _platform.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (platform) {
this.parsedResult.platform = platform.describe(this.getUA());
}
return this.parsedResult.platform;
}
/**
* Get parsed engine
* @return {{}}
*/
getEngine() {
if (this.parsedResult.engine) {
return this.parsedResult.engine;
}
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 {{}}
*/
parseEngine() {
this.parsedResult.engine = {};
const engine = Utils.find(enginesParsersList, (_engine) => {
if (typeof _engine.test === 'function') {
return _engine.test(this);
}
if (Array.isArray(_engine.test)) {
return _engine.test.some(condition => this.test(condition));
}
throw new Error("Browser's test function is not valid");
});
if (engine) {
this.parsedResult.engine = engine.describe(this.getUA());
}
return this.parsedResult.engine;
}
/**
* Parse full information about the browser
* @returns {Parser}
*/
parse() {
this.parseBrowser();
this.parseOS();
this.parsePlatform();
this.parseEngine();
return this;
}
/**
* Get parsed result
* @return {ParsedResult}
*/
getResult() {
return Utils.assign({}, this.parsedResult);
}
/**
* Check if parsed browser matches certain conditions
*
* @param {Object} checkTree It's one or two layered object,
* which can include a platform or an OS on the first layer
* and should have browsers specs on the bottom-laying layer
*
* @returns {Boolean|undefined} Whether the browser satisfies the set conditions or not.
* Returns `undefined` when the browser is no described in the checkTree object.
*
* @example
* const browser = Bowser.getParser(window.navigator.userAgent);
* if (browser.satisfies({chrome: '>118.01.1322' }))
* // or with os
* if (browser.satisfies({windows: { chrome: '>118.01.1322' } }))
* // or with platforms
* if (browser.satisfies({desktop: { chrome: '>118.01.1322' } }))
*/
satisfies(checkTree) {
const platformsAndOSes = {};
let platformsAndOSCounter = 0;
const browsers = {};
let browsersCounter = 0;
const allDefinitions = Object.keys(checkTree);
allDefinitions.forEach((key) => {
const currentDefinition = checkTree[key];
if (typeof currentDefinition === 'string') {
browsers[key] = currentDefinition;
browsersCounter += 1;
} else if (typeof currentDefinition === 'object') {
platformsAndOSes[key] = currentDefinition;
platformsAndOSCounter += 1;
}
});
if (platformsAndOSCounter > 0) {
const platformsAndOSNames = Object.keys(platformsAndOSes);
const OSMatchingDefinition = Utils.find(platformsAndOSNames, name => (this.isOS(name)));
if (OSMatchingDefinition) {
const osResult = this.satisfies(platformsAndOSes[OSMatchingDefinition]);
if (osResult !== void 0) {
return osResult;
}
}
const platformMatchingDefinition = Utils.find(
platformsAndOSNames,
name => (this.isPlatform(name)),
);
if (platformMatchingDefinition) {
const platformResult = this.satisfies(platformsAndOSes[platformMatchingDefinition]);
if (platformResult !== void 0) {
return platformResult;
}
}
}
if (browsersCounter > 0) {
const browserNames = Object.keys(browsers);
const matchingDefinition = Utils.find(browserNames, name => (this.isBrowser(name, true)));
if (matchingDefinition !== void 0) {
return this.compareVersion(browsers[matchingDefinition]);
}
}
return undefined;
}
/**
* Check if the browser name equals the passed string
* @param {string} browserName The string to compare with the browser name
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {boolean}
*/
isBrowser(browserName, includingAlias = false) {
const defaultBrowserName = this.getBrowserName().toLowerCase();
let browserNameLower = browserName.toLowerCase();
const alias = Utils.getBrowserTypeByAlias(browserNameLower);
if (includingAlias && alias) {
browserNameLower = alias.toLowerCase();
}
return browserNameLower === defaultBrowserName;
}
compareVersion(version) {
let expectedResults = [0];
let comparableVersion = version;
let isLoose = false;
const currentBrowserVersion = this.getBrowserVersion();
if (typeof currentBrowserVersion !== 'string') {
return void 0;
}
if (version[0] === '>' || version[0] === '<') {
comparableVersion = version.substr(1);
if (version[1] === '=') {
isLoose = true;
comparableVersion = version.substr(2);
} else {
expectedResults = [];
}
if (version[0] === '>') {
expectedResults.push(1);
} else {
expectedResults.push(-1);
}
} else if (version[0] === '=') {
comparableVersion = version.substr(1);
} else if (version[0] === '~') {
isLoose = true;
comparableVersion = version.substr(1);
}
return expectedResults.indexOf(
Utils.compareVersions(currentBrowserVersion, comparableVersion, isLoose),
) > -1;
}
/**
* Check if the OS name equals the passed string
* @param {string} osName The string to compare with the OS name
* @returns {boolean}
*/
isOS(osName) {
return this.getOSName(true) === String(osName).toLowerCase();
}
/**
* Check if the platform type equals the passed string
* @param {string} platformType The string to compare with the platform type
* @returns {boolean}
*/
isPlatform(platformType) {
return this.getPlatformType(true) === String(platformType).toLowerCase();
}
/**
* Check if the engine name equals the passed string
* @param {string} engineName The string to compare with the engine name
* @returns {boolean}
*/
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"
* @param {String} anything
* @param [includingAlias=false] The flag showing whether alias will be included into comparison
* @returns {Boolean}
*/
is(anything, includingAlias = false) {
return this.isBrowser(anything, includingAlias) || this.isOS(anything)
|| this.isPlatform(anything);
}
/**
* Check if any of the given values satisfies this.is(anything)
* @param {String[]} anythings
* @returns {Boolean}
*/
some(anythings = []) {
return anythings.some(anything => this.is(anything));
}
}
export default Parser;

File diff suppressed because it is too large Load Diff

309
src/utils.js Normal file
View File

@ -0,0 +1,309 @@
import { BROWSER_MAP, BROWSER_ALIASES_MAP } from './constants.js';
export default class Utils {
/**
* Get first matched item for a string
* @param {RegExp} regexp
* @param {String} ua
* @return {Array|{index: number, input: string}|*|boolean|string}
*/
static getFirstMatch(regexp, ua) {
const match = ua.match(regexp);
return (match && match.length > 0 && match[1]) || '';
}
/**
* Get second matched item for a string
* @param regexp
* @param {String} ua
* @return {Array|{index: number, input: string}|*|boolean|string}
*/
static getSecondMatch(regexp, ua) {
const match = ua.match(regexp);
return (match && match.length > 1 && match[2]) || '';
}
/**
* Match a regexp and return a constant or undefined
* @param {RegExp} regexp
* @param {String} ua
* @param {*} _const Any const that will be returned if regexp matches the string
* @return {*}
*/
static matchAndReturnConst(regexp, ua, _const) {
if (regexp.test(ua)) {
return _const;
}
return void (0);
}
static getWindowsVersionName(version) {
switch (version) {
case 'NT': return 'NT';
case 'XP': return 'XP';
case 'NT 5.0': return '2000';
case 'NT 5.1': return 'XP';
case 'NT 5.2': return '2003';
case 'NT 6.0': return 'Vista';
case 'NT 6.1': return '7';
case 'NT 6.2': return '8';
case 'NT 6.3': return '8.1';
case 'NT 10.0': return '10';
default: return undefined;
}
}
/**
* Get macOS version name
* 10.5 - Leopard
* 10.6 - Snow Leopard
* 10.7 - Lion
* 10.8 - Mountain Lion
* 10.9 - Mavericks
* 10.10 - Yosemite
* 10.11 - El Capitan
* 10.12 - Sierra
* 10.13 - High Sierra
* 10.14 - Mojave
* 10.15 - Catalina
*
* @example
* getMacOSVersionName("10.14") // 'Mojave'
*
* @param {string} version
* @return {string} versionName
*/
static getMacOSVersionName(version) {
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
v.push(0);
if (v[0] !== 10) return undefined;
switch (v[1]) {
case 5: return 'Leopard';
case 6: return 'Snow Leopard';
case 7: return 'Lion';
case 8: return 'Mountain Lion';
case 9: return 'Mavericks';
case 10: return 'Yosemite';
case 11: return 'El Capitan';
case 12: return 'Sierra';
case 13: return 'High Sierra';
case 14: return 'Mojave';
case 15: return 'Catalina';
default: return undefined;
}
}
/**
* Get Android version name
* 1.5 - Cupcake
* 1.6 - Donut
* 2.0 - Eclair
* 2.1 - Eclair
* 2.2 - Froyo
* 2.x - Gingerbread
* 3.x - Honeycomb
* 4.0 - Ice Cream Sandwich
* 4.1 - Jelly Bean
* 4.4 - KitKat
* 5.x - Lollipop
* 6.x - Marshmallow
* 7.x - Nougat
* 8.x - Oreo
* 9.x - Pie
*
* @example
* getAndroidVersionName("7.0") // 'Nougat'
*
* @param {string} version
* @return {string} versionName
*/
static getAndroidVersionName(version) {
const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
v.push(0);
if (v[0] === 1 && v[1] < 5) return undefined;
if (v[0] === 1 && v[1] < 6) return 'Cupcake';
if (v[0] === 1 && v[1] >= 6) return 'Donut';
if (v[0] === 2 && v[1] < 2) return 'Eclair';
if (v[0] === 2 && v[1] === 2) return 'Froyo';
if (v[0] === 2 && v[1] > 2) return 'Gingerbread';
if (v[0] === 3) return 'Honeycomb';
if (v[0] === 4 && v[1] < 1) return 'Ice Cream Sandwich';
if (v[0] === 4 && v[1] < 4) return 'Jelly Bean';
if (v[0] === 4 && v[1] >= 4) return 'KitKat';
if (v[0] === 5) return 'Lollipop';
if (v[0] === 6) return 'Marshmallow';
if (v[0] === 7) return 'Nougat';
if (v[0] === 8) return 'Oreo';
if (v[0] === 9) return 'Pie';
return undefined;
}
/**
* Get version precisions count
*
* @example
* getVersionPrecision("1.10.3") // 3
*
* @param {string} version
* @return {number}
*/
static getVersionPrecision(version) {
return version.split('.').length;
}
/**
* Calculate browser version weight
*
* @example
* compareVersions('1.10.2.1', '1.8.2.1.90') // 1
* compareVersions('1.010.2.1', '1.09.2.1.90'); // 1
* compareVersions('1.10.2.1', '1.10.2.1'); // 0
* compareVersions('1.10.2.1', '1.0800.2'); // -1
* compareVersions('1.10.2.1', '1.10', true); // 0
*
* @param {String} versionA versions versions to compare
* @param {String} versionB versions versions to compare
* @param {boolean} [isLoose] enable loose comparison
* @return {Number} comparison result: -1 when versionA is lower,
* 1 when versionA is bigger, 0 when both equal
*/
/* eslint consistent-return: 1 */
static compareVersions(versionA, versionB, isLoose = false) {
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
const versionAPrecision = Utils.getVersionPrecision(versionA);
const versionBPrecision = Utils.getVersionPrecision(versionB);
let precision = Math.max(versionAPrecision, versionBPrecision);
let lastPrecision = 0;
const chunks = Utils.map([versionA, versionB], (version) => {
const delta = precision - Utils.getVersionPrecision(version);
// 2) "9" -> "9.0" (for precision = 2)
const _version = version + new Array(delta + 1).join('.0');
// 3) "9.0" -> ["000000000"", "000000009"]
return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
});
// adjust precision for loose comparison
if (isLoose) {
lastPrecision = precision - Math.min(versionAPrecision, versionBPrecision);
}
// iterate in reverse order by reversed chunks array
precision -= 1;
while (precision >= lastPrecision) {
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
if (chunks[0][precision] > chunks[1][precision]) {
return 1;
}
if (chunks[0][precision] === chunks[1][precision]) {
if (precision === lastPrecision) {
// all version chunks are same
return 0;
}
precision -= 1;
} else if (chunks[0][precision] < chunks[1][precision]) {
return -1;
}
}
return undefined;
}
/**
* Array::map polyfill
*
* @param {Array} arr
* @param {Function} iterator
* @return {Array}
*/
static map(arr, iterator) {
const result = [];
let i;
if (Array.prototype.map) {
return Array.prototype.map.call(arr, iterator);
}
for (i = 0; i < arr.length; i += 1) {
result.push(iterator(arr[i]));
}
return result;
}
/**
* Array::find polyfill
*
* @param {Array} arr
* @param {Function} predicate
* @return {Array}
*/
static find(arr, predicate) {
let i;
let l;
if (Array.prototype.find) {
return Array.prototype.find.call(arr, predicate);
}
for (i = 0, l = arr.length; i < l; i += 1) {
const value = arr[i];
if (predicate(value, i)) {
return value;
}
}
return undefined;
}
/**
* Object::assign polyfill
*
* @param {Object} obj
* @param {Object} ...objs
* @return {Object}
*/
static assign(obj, ...assigners) {
const result = obj;
let i;
let l;
if (Object.assign) {
return Object.assign(obj, ...assigners);
}
for (i = 0, l = assigners.length; i < l; i += 1) {
const assigner = assigners[i];
if (typeof assigner === 'object' && assigner !== null) {
const keys = Object.keys(assigner);
keys.forEach((key) => {
result[key] = assigner[key];
});
}
}
return obj;
}
/**
* Get short version/alias for a browser name
*
* @example
* getBrowserAlias('Microsoft Edge') // edge
*
* @param {string} browserName
* @return {string}
*/
static getBrowserAlias(browserName) {
return BROWSER_ALIASES_MAP[browserName];
}
/**
* Get browser name for a short version/alias
*
* @example
* getBrowserTypeByAlias('edge') // Microsoft Edge
*
* @param {string} browserAlias
* @return {string}
*/
static getBrowserTypeByAlias(browserAlias) {
return BROWSER_MAP[browserAlias] || '';
}
}

View File

@ -0,0 +1,21 @@
import test from 'ava';
import yaml from 'yamljs';
import path from 'path';
import Bowser from '../../src/bowser';
import BowserBuild from '../../es5';
const listOfUA = yaml.load(path.join(__dirname, 'useragentstrings.yml'));
const browserNames = Object.keys(listOfUA);
browserNames.forEach((browserName) => {
listOfUA[browserName].forEach((browser, index) => {
test(`Test ${browserName} ${index}`, (t) => {
const parsed = Bowser.parse(browser.ua);
const parsedBuild = BowserBuild.parse(browser.ua);
t.deepEqual(parsed, browser.spec, `${browser.ua}`);
t.deepEqual(parsedBuild, browser.spec, `${browser.ua}`);
t.is(parsed.browser.name, browserName, `${browser.ua}`);
});
});
});

File diff suppressed because it is too large Load Diff

View File

@ -1,151 +0,0 @@
/**
* Loop through all entries in our user agents object and test everything.
*
* @see src/useragents.js
* @author hannes.diercks@jimdo.com
*/
var g
, ua
, p
, assert = require('assert')
, browser = require('../src/bowser')
, allUserAgents = require('../src/useragents').useragents
/**
* Get the length of an object.
* http://stackoverflow.com/questions/5223/length-of-javascript-object-ie-associative-array
*
* @param {Object} obj
* @return {Number}
*/
function objLength(obj) {
var size = 0
, key
for (key in obj) {
if (obj.hasOwnProperty(key)) size++
}
return size
}
function objKeys(obj) {
var keys = []
, key
for (key in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key)
}
}
keys.sort();
return keys.join(', ')
}
/* Groups */
for (g in allUserAgents) { (function(group, userAgents) {
describe(group, function() {
/* User Agents */
for (ua in userAgents) { (function(userAgent, expections) {
describe('user agent "' + userAgent + '"', function() {
expections.name = group
/* Get the result from bowser. */
var result = browser._detect(userAgent)
/* At first, check if the result has the correct length. */
it('should have ' + objLength(expections) + ' properties', function() {
assert.equal(objKeys(result), objKeys(expections))
})
/* Properties */
for (p in expections) { (function(property, value, resultValue) {
/* Now ensure correctness of every property. */
it('\'s Property "' + property + '" should be ' + value, function() {
assert.equal(resultValue, value)
})
})(p, expections[p], result[p])}
})
})(ua, userAgents[ua])}
})
})(g, allUserAgents[g])}
var comparisionsTasks = [
['9.0', '10', -1],
['11', '10', 1],
['1.10.2.1', '1.8.2.1.90', 1],
['1.010.2.1', '1.08.2.1.90', 1],
['1.10.2.1', '1.10.2.1', 0],
['1.10.2.1', '1.0800.2', -1],
['1.0.0-alpha', '1.0.0-alpha.1', -1],
['1.0.0-alpha.1', '1.0.0-alpha.beta', -1],
['1.0.0-alpha.beta', '1.0.0-beta', -1],
['1.0.0-beta', '1.0.0-beta.2', -1],
['1.0.0-beta.11', '1.0.0-rc.1', -1],
['1.0.0-rc.1', '1.0.0', -1]
];
describe('Browser versions comparision', function() {
for(g in comparisionsTasks) {
var task = comparisionsTasks[g],
version = task[0],
version2 = task[1],
matching = task[2] === 0 ? ' == ' : (task[2] > 0) ? ' > ' : ' < ';
it('version ' + version + ' should be' + matching + 'version ' + version2, function(){
assert.equal(browser.compareVersions([version, version2]), task[2]);
});
}
});
describe('Unsupported browser check', function() {
before(function() {
this.ie10_6 = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0";
});
it('should be passed by #isUnsupportedBrowser for IE10.6 and for IE10 miminal version specified', function() {
var unsupported = browser.isUnsupportedBrowser({msie: "10"}, this.ie10_6);
assert.equal(unsupported, false);
});
it('should be passed by #isUnsupportedBrowser for IE10.6 and for IE10 miminal version specified in strict mode', function() {
var unsupported = browser.isUnsupportedBrowser({msie: "10"}, true, this.ie10_6);
assert.equal(unsupported, false);
});
it('should NOT be passed by #isUnsupportedBrowser for IE10.6 and for IE10 miminal version specified in strict mode', function() {
var isUnsupported = browser.isUnsupportedBrowser({msie: "11"}, true, this.ie10_6);
assert.equal(isUnsupported, true);
});
it('should NOT be passed by #check for IE10.6 and for IE11 miminal version specified', function() {
var supported = browser.check({msie: "11"}, this.ie10_6);
assert.equal(supported, false);
});
it('should NOT be passed by #check for IE10.6 and for IE11 miminal version specified in strict mode', function() {
var supported = browser.check({msie: "11"}, true, this.ie10_6);
assert.equal(supported, false);
});
it('should throw an error when minVersion map has a number, but not a string', function() {
assert.throws(() => {
browser.check({msie: 11}, this.ie10_6);
}, /Browser version in the minVersion map should be a string/);
});
it('should be passed by #check for IE10.6 when version was not specified', function() {
var supported = browser.check({}, this.ie10_6);
assert.equal(supported, true);
});
it('should NOT be passed by #check for IE10.6 when version was not specified in strict mode', function() {
var supported = browser.check({}, true, this.ie10_6);
assert.equal(supported, false);
});
})

18
test/unit/bowser.js Normal file
View File

@ -0,0 +1,18 @@
import test from 'ava';
import Bowser from '../../src/bowser';
import Parser from '../../src/parser';
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.1165';
const browser = Bowser.getParser(UA);
test('Bowser`s constructor returns a Parser instance', (t) => {
t.truthy(browser instanceof Parser);
});
test('Bowser`s constructor fails if UA is empty', (t) => {
t.throws(() => (Bowser.getParser()));
});
test('Bowser.parse parses UA and returns result', (t) => {
t.deepEqual(Bowser.parse(UA), browser.getResult());
});

15
test/unit/constants.js Normal file
View File

@ -0,0 +1,15 @@
import test from 'ava';
import { BROWSER_ALIASES_MAP } from '../../src/constants';
test('check duplicate aliases', (t) => {
const aliasesList = Object.keys(BROWSER_ALIASES_MAP).map(value => (BROWSER_ALIASES_MAP[value]));
let foundOnce, foundTwice;
const duplicates = aliasesList.filter(item => {
foundOnce = aliasesList.indexOf(item);
foundTwice = aliasesList.indexOf(item, foundOnce + 1);
return +foundTwice !== -1;
});
t.deepEqual(duplicates, []);
});

230
test/unit/parser.js Normal file
View File

@ -0,0 +1,230 @@
import test from 'ava';
import sinon from 'sinon';
import Parser from '../../src/parser';
import Bowser from '../../src/bowser';
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.1165';
const parser = new Parser(UA, true);
const EDGE_UA = 'Mozilla/5.0 (Linux; Android 8.0; Pixel XL Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.0 Mobile Safari/537.36 EdgA/41.1.35.1';
const edgeParser = new Parser(EDGE_UA, true);
const FOCUS_UA = 'Mozilla/5.0 (Linux; Android 7.1.1) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Focus/1.2.1 Chrome/59.0.3071.125';
const focusParser = new Parser(FOCUS_UA, true);
test('constructor', (t) => {
t.truthy(parser instanceof Parser);
});
test('Parser.getUA returns a correct UA', (t) => {
t.is(parser.getUA(), UA);
});
test('Parser.test', (t) => {
t.truthy(parser.test(/Chrome/i));
});
test('Parser.parseBrowser is being called when the Parser.getBrowser() is called', (t) => {
const spy = sinon.spy(parser, 'parseBrowser');
const b = parser.getBrowser();
t.truthy(spy.called);
t.is(b.name, 'Opera');
t.is(b.version, '43.0.2442.1165');
parser.parseBrowser.restore();
});
test('Parser.getBrowserName returns a correct result', (t) => {
t.is(parser.getBrowserName(), 'Opera');
});
test('Parser.getBrowserVersion returns a correct result', (t) => {
t.is(parser.getBrowserVersion(), '43.0.2442.1165');
});
test('Parser.parseOS is being called when getOS() called', (t) => {
const spy = sinon.spy(parser, 'parseOS');
parser.getOS();
t.truthy(spy.called);
parser.parseOS.restore();
});
test('Parser.getOSName gives a name of the browser', (t) => {
t.is(parser.getOSName(), 'macOS');
});
test('Parser.getOSName gives a lower-cased name of the browser', (t) => {
t.is(parser.getOSName(true), 'macos');
});
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(), {});
});
test('Parser.satisfies should make simple comparisons', (t) => {
// also covers Parser.compareVersion() method
t.is(parser.satisfies({ opera: '>42' }), true);
t.is(parser.satisfies({ opera: '<44' }), true);
t.is(parser.satisfies({ opera: '=43.0.2442.1165' }), true);
t.is(parser.satisfies({ opera: '~43.0' }), true);
t.is(parser.satisfies({ opera: '>=43' }), true);
t.is(parser.satisfies({ opera: '<=43' }), true);
t.is(parser.satisfies({ opera: '>=43.0' }), true);
t.is(parser.satisfies({ opera: '>=43.0.2442.1165' }), true);
t.is(parser.satisfies({ opera: '<=43.0.2442.1165' }), true);
t.is(parser.satisfies({ opera: '>=43.0.2443' }), false);
t.is(parser.satisfies({ opera: '<=43.0.2443' }), true);
t.is(parser.satisfies({ opera: '>=43.0.2441' }), true);
t.is(parser.satisfies({ opera: '~43' }), true);
});
test('Parser.satisfies should make complex comparison', (t) => {
t.is(parser.satisfies({
macos: {
safari: '>11',
},
ios: {
safari: '>10',
},
opera: '>42',
}), true);
});
test('Parser.satisfies should respect platform and OS specific declarations', (t) => {
t.is(parser.satisfies({
macos: {
opera: '>45',
},
opera: '>42',
}), false);
t.is(parser.satisfies({
desktop: {
opera: '>45',
},
opera: '>42',
}), false);
t.is(parser.satisfies({
macos: {
opera: '>45',
},
desktop: {
opera: '>42',
},
opera: '>42',
}), false);
t.is(parser.satisfies({
macos: {
chrome: '>45',
},
desktop: {
chrome: '>42',
},
firefox: '>42',
}), void 0);
});
test('Parser.satisfies for versionless UA strings', (t) => {
const _parser = new Parser('Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15G77 [FBAN/FBIOS;FBDV/iPhone7,2;FBMD/iPhone;FBSN/iOS;FBSV/11.4.1;FBSS/2;FBCR/vfnl;FBID/phone;FBLC/nl_NL;FBOP/5;FBRV/0]');
t.is(_parser.satisfies({
safari: '>9',
}), void 0);
});
test('Parser.satisfies should consider aliases while handling browsers', (t) => {
t.is(edgeParser.satisfies({ 'Microsoft Edge': '=41.1.35.1' }), true);
t.is(edgeParser.satisfies({ 'microsoft edge': '=41.1.35.1' }), true);
t.is(edgeParser.satisfies({ 'edge': '=41.1.35.1' }), true);
t.is(edgeParser.satisfies({ 'Edge': '=41.1.35.1' }), true);
});
test('Parser.is should pass', (t) => {
t.is(parser.is('opera'), true);
t.is(parser.is('desktop'), true);
t.is(parser.is('macos'), true);
});
test('Parser.is should pass when not including aliases', (t) => {
t.is(edgeParser.is('Microsoft Edge', false), true);
t.is(edgeParser.is('microsoft edge', false), true);
t.is(edgeParser.is('mIcrosoft eDge', false), true);
t.is(edgeParser.is('edge', false), false);
t.is(edgeParser.is('Edge', false), false);
t.is(edgeParser.is('desktop', false), false);
t.is(edgeParser.is('macos', false), false);
t.is(edgeParser.is('mobile', false), true);
t.is(edgeParser.is('android', false), true);
});
test('Parser.is should pass when including aliases', (t) => {
t.is(edgeParser.is('Microsoft Edge', true), true);
t.is(edgeParser.is('microsoft edge', true), true);
t.is(edgeParser.is('mIcrosoft eDge', true), true);
t.is(edgeParser.is('edge', true), true);
t.is(edgeParser.is('Edge', true), true);
t.is(edgeParser.is('desktop', true), false);
t.is(edgeParser.is('macos', true), false);
t.is(edgeParser.is('mobile', true), true);
t.is(edgeParser.is('android', true), true);
});
test('Parser.is using constants should pass', (t) => {
t.is(parser.is(Bowser.BROWSER_MAP.opera), true);
t.is(parser.is(Bowser.PLATFORMS_MAP.desktop), true);
t.is(parser.is(Bowser.OS_MAP.MacOS), true);
});
test('Parser.some should pass', (t) => {
t.is(parser.some(['opera', 'chrome', 'firefox']), true);
t.is(parser.some(['macos', 'windows']), true);
t.is(parser.some(['chrome', 'firefox']), false);
t.is(parser.some([]), false);
t.is(parser.some(), false);
});
test('Parser.isBrowser should pass when not loosely checking', (t) => {
t.is(edgeParser.isBrowser('Microsoft Edge', false), true);
t.is(edgeParser.isBrowser('microsoft edge', false), true);
t.is(edgeParser.isBrowser('mIcrosoft eDge', false), true);
t.is(edgeParser.isBrowser('edge', false), false);
t.is(edgeParser.isBrowser('Edge', false), false);
});
test('Parser.isBrowser should pass when loosely checking', (t) => {
t.is(edgeParser.isBrowser('Microsoft Edge', true), true);
t.is(edgeParser.isBrowser('microsoft edge', true), true);
t.is(edgeParser.isBrowser('mIcrosoft eDge', true), true);
t.is(edgeParser.isBrowser('edge', true), true);
t.is(edgeParser.isBrowser('Edge', true), true);
});
test('Parser.isBrowser should pass for non-aliased browsers', (t) => {
t.is(focusParser.isBrowser('Focus', true), true);
t.is(focusParser.isBrowser('Focus', false), true);
});
test('Parser.isEngine should pass', (t) => {
t.is(parser.isEngine('blink'), true);
t.is(parser.isEngine('webkit'), false);
});

140
test/unit/utils.js Normal file
View File

@ -0,0 +1,140 @@
import test from 'ava';
import {
getFirstMatch,
getSecondMatch,
matchAndReturnConst,
getWindowsVersionName,
getMacOSVersionName,
getAndroidVersionName,
getVersionPrecision,
compareVersions,
map,
find,
assign,
getBrowserAlias,
getBrowserTypeByAlias
} from '../../src/utils';
test('getFirstMatch', (t) => {
const matchedVersion = getFirstMatch(/version\/(\S+)/i, 'Chrome Version/11.11.11');
t.is(matchedVersion, '11.11.11');
});
test('getSecondMatch', (t) => {
const matchedVersion = getSecondMatch(/version\/(\S+).*version\/(\S+)/i, 'Chrome Version/11.11.11 Chrome Version/22.22.22');
t.is(matchedVersion, '22.22.22');
});
test('matchAndReturnConst', (t) => {
const _const = matchAndReturnConst(/version/i, 'version', "_const");
t.is(_const, '_const');
});
test('getWindowsVersionName', (t) => {
t.is(getWindowsVersionName('NT 5.0'), '2000');
t.is(getWindowsVersionName('XXX'), void 0);
});
test('getMacOSVersionName', (t) => {
t.is(getMacOSVersionName('10.14.5'), 'Mojave');
t.is(getMacOSVersionName('10.15'), 'Catalina');
t.is(getMacOSVersionName('10.999999'), void 0);
t.is(getMacOSVersionName('XXX'), void 0);
});
test('getAndroidVersionName', (t) => {
t.is(getAndroidVersionName('1.0'), void 0);
t.is(getAndroidVersionName('8.0'), 'Oreo');
t.is(getAndroidVersionName('9'), 'Pie');
t.is(getAndroidVersionName('XXX'), void 0);
});
test('getVersionPrecision', (t) => {
const precision = getVersionPrecision("10.14.5");
t.is(precision, 3);
});
test('compareVersions', (t) => {
const comparisionsTasks = [
['9.0', '10', -1],
['11', '10', 1],
['1.10.2.1', '1.8.2.1.90', 1],
['1.010.2.1', '1.08.2.1.90', 1],
['1.10.2.1', '1.10.2.1', 0],
['1.10.2.1', '1.10.2', 0, true],
['1.10.2.1', '1.10', 0, true],
['1.10.2.1', '1', 0, true],
['1.10.2.1', '1.0800.2', -1],
['1.0.0-alpha', '1.0.0-alpha.1', -1],
['1.0.0-alpha.1', '1.0.0-alpha.beta', -1],
['1.0.0-alpha.beta', '1.0.0-beta', -1],
['1.0.0-beta', '1.0.0-beta.2', -1],
['1.0.0-beta.11', '1.0.0-rc.1', -1],
['1.0.0-rc.1', '1.0.0', -1],
];
comparisionsTasks.forEach((testingParams) => {
const versionA = testingParams[0];
const versionB = testingParams[1];
const result = testingParams[2];
const isLoose = testingParams.length > 3 ? testingParams[3] : false;
let matching = isLoose ? '~' : ' == ';
if (result > 0) {
matching = ' > ';
} else if (result < 0) {
matching = ' < ';
}
t.is(compareVersions(versionA, versionB, isLoose), result, `version ${versionA} should be ${matching} version ${versionB}`);
});
});
test('map', (t) => {
const result = map([1,2], (value) => value+2);
t.is(result[0], 3);
t.is(result[1], 4);
const original = Array.prototype.map;
delete Array.prototype.map;
const polyfillResult = map([1,2], (value) => value+2);
Array.prototype.map = original;
t.is(polyfillResult[0], 3);
t.is(polyfillResult[1], 4);
});
test('find', (t) => {
const result = find([1,2], (value) => value==2);
t.is(result, 2);
const original = Array.prototype.find;
delete Array.prototype.find;
const polyfillResultFound = find([1,2], (value) => value==2);
const polyfillResultNotFound = find([1,2], (value) => value==3);
Array.prototype.find = original;
t.is(polyfillResultFound, 2);
t.is(polyfillResultNotFound, undefined);
});
test('assign', (t) => {
const result = assign({}, { a: 1 }, { b: 1 }, { b: 2, c: 3 });
t.is(result['a'], 1);
t.is(result['b'], 2);
t.is(result['c'], 3);
const original = Object.assign;
delete Object.assign;
const polyfillResult = assign({}, { a: 1 }, { b: 1 }, null, { b: 2, c: 3 });
Object.assign = original;
t.is(polyfillResult['a'], 1);
t.is(polyfillResult['b'], 2);
t.is(polyfillResult['c'], 3);
});
test('getBrowserAlias', (t) => {
t.is(getBrowserAlias('Microsoft Edge'), 'edge');
t.is(getBrowserAlias('Unexisting Browser'), void 0);
});
test('getBrowserTypeByAlias', (t) => {
t.is(getBrowserTypeByAlias('edge'), 'Microsoft Edge');
t.is(getBrowserTypeByAlias(void 0), '');
});

109
typings.d.ts vendored
View File

@ -1,109 +0,0 @@
// Type definitions for Bowser 1.x
// Project: https://github.com/lancedikson/bowser
// Definitions by: Paulo Cesar <https://github.com/pocesar>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
declare const bowser: bowser.IBowser;
export = bowser;
export as namespace bowser;
declare namespace bowser {
export interface IBowserOS {
mac: boolean;
/**other than Windows Phone */
windows: boolean;
windowsphone: boolean;
/**other than android, chromeos, webos, tizen, and sailfish */
linux: boolean;
chromeos: boolean;
android: boolean;
/** also sets one of iphone/ipad/ipod */
ios: boolean;
blackberry: boolean;
firefoxos: boolean;
/** may also set touchpad */
webos: boolean;
bada: boolean;
tizen: boolean;
sailfish: boolean;
}
export interface IBowserVersions {
chrome: boolean;
chromium: boolean;
firefox: boolean;
msie: boolean;
msedge: boolean;
safari: boolean;
android: boolean;
ios: boolean;
opera: boolean;
phantom: boolean;
blackberry: boolean;
webos: boolean;
silk: boolean;
bada: boolean;
tizen: boolean;
seamonkey: boolean;
sailfish: boolean;
ucbrowser: boolean;
qupzilla: boolean;
vivaldi: boolean;
sleipnir: boolean;
kMeleon: boolean;
}
export interface IBowserEngines {
/** IE <= 11 */
msie: boolean;
/**Chrome 0-27, Android <4.4, iOs, BB, etc. */
webkit: boolean;
/**Chrome >=28, Android >=4.4, Opera, etc. */
blink: boolean;
/**Firefox, etc. */
gecko: boolean;
/** IE > 11 */
msedge: boolean;
/** If a tablet device is detected, the flag tablet is set instead of mobile. */
tablet: boolean;
/** All detected mobile OSes are additionally flagged mobile, unless it's a tablet */
mobile: boolean;
}
export interface IBowserGrade {
/** Grade A browser */
a: boolean;
/** Grade C browser */
c: boolean;
/** Grade X browser */
x: boolean;
/** A human readable name for this browser. E.g. 'Chrome', '' */
name: string;
/** Version number for the browser. E.g. '32.0' */
version: string|number;
/** Name for this operating system. E.g. 'macOS' */
osname: string;
/** Version number for this operating system. E.g. '10.12.6' */
osversion: string|number;
}
export interface IBowserDetection extends IBowserGrade, IBowserEngines, IBowserOS, IBowserVersions { }
export interface IBowserMinVersions {
// { msie: "11", "firefox": "4" }
[index: string]: string;
}
export interface IBowser extends IBowserDetection {
(): IBowserDetection;
test(browserList: string[]): boolean;
_detect(ua: string): IBowser;
detect(ua: string): IBowser;
compareVersions(versions: string[]): number;
check(minVersions: IBowserMinVersions, strictMode?: boolean|string, ua?: string): Boolean;
isUnsupportedBrowser(minVersions: IBowserMinVersions, strictMode?: boolean|string, ua?: string): boolean;
}
}

43
webpack.config.js Normal file
View File

@ -0,0 +1,43 @@
const path = require('path');
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
plugins: [
new CompressionPlugin(),
],
mode: 'production', // "production" | "development" | "none"
// Chosen mode tells webpack to use its built-in optimizations accordingly.
entry: {
bundled: ['@babel/polyfill', './src/bowser.js'],
es5: './src/bowser.js',
}, // string | object | array
// defaults to ./src
// Here the application starts executing
// and webpack starts bundling
output: {
// options related to how webpack emits results
path: path.resolve(__dirname, './'), // string
// the target directory for all output files
// must be an absolute path (use the Node.js path module)
filename: '[name].js', // string
// the filename template for entry chunks
library: 'bowser',
libraryTarget: 'umd', // universal module definition
// the type of the exported library
globalObject: 'this',
},
module: {
// configuration regarding modules
rules: [
// rules for modules (configure loaders, parser options, etc.)
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
},
},
],
},
};