From 7a4fe6f4549fdd91412961293c6a90224c83bfba Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 28 Mar 2023 10:41:59 +0700 Subject: [PATCH] Fix #227 #237 #488 : Provide extensions - initial work --- package.json | 6 +++++- src/ua-parser-extension.js | 32 ++++++++++++++++++++++++++++++++ src/ua-parser-extension.mjs | 36 ++++++++++++++++++++++++++++++++++++ test/test-extension.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/ua-parser-extension.js create mode 100644 src/ua-parser-extension.mjs create mode 100644 test/test-extension.js diff --git a/package.json b/package.json index 8617384..e10152a 100644 --- a/package.json +++ b/package.json @@ -151,6 +151,10 @@ "./enums" : { "require": "./src/ua-parser-enum.js", "import": "./src/ua-parser-enum.mjs" + }, + "./extensions" : { + "require": "./src/ua-parser-extension.js", + "import": "./src/ua-parser-extension.mjs" } }, "files": [ @@ -158,7 +162,7 @@ "src" ], "scripts": { - "build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle && node -e \"const fs=require('fs');fs.writeFileSync('src/ua-parser.mjs','// Generated ESM version of UAParser.js\\n// Source file: /src/ua-parser.js\\n\\nconst window = undefined;\\n\\n'+fs.readFileSync('src/ua-parser.js','utf-8').replace(/\\(func[\\s\\S]+strict\\';/ig,'').replace(/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'),'utf-8');fs.writeFileSync('src/ua-parser-enum.mjs','// Generated ESM version of UAParser.js enums\\n// Source file: /src/ua-parser-enum.js\\n\\n'+fs.readFileSync('src/ua-parser-enum.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8')\"", + "build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/^ UA/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/^ UA/' --compress --mangle && uglifyjs src/ua-parser-enum.js -o dist/ua-parser-enum.min.js --comments '/^ Enum/' && node -e \"const fs=require('fs');fs.writeFileSync('src/ua-parser.mjs','// Generated ESM version of UAParser.js\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser.js\\n\\nconst window = undefined;\\n\\n'+fs.readFileSync('src/ua-parser.js','utf-8').replace(/\\(func[\\s\\S]+strict\\';/ig,'').replace(/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'),'utf-8');fs.writeFileSync('src/ua-parser-enum.mjs','// Generated ESM version of UAParser.js enums\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser-enum.js\\n\\n'+fs.readFileSync('src/ua-parser-enum.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8');fs.writeFileSync('src/ua-parser-extension.mjs','// Generated ESM version of UAParser.js extensions\\n// DO NOT EDIT THIS FILE!\\n// Source: /src/ua-parser-extension.js\\n\\n'+fs.readFileSync('src/ua-parser-extension.js','utf-8').replace(/module\\.exports =/ig,'export'),'utf-8')\"", "test": "jshint src/ua-parser.js && mocha -R nyan test", "test-ci": "jshint src/ua-parser.js && mocha -R spec test", "verup": "node ./node_modules/verup", diff --git a/src/ua-parser-extension.js b/src/ua-parser-extension.js new file mode 100644 index 0000000..fc4b3bc --- /dev/null +++ b/src/ua-parser-extension.js @@ -0,0 +1,32 @@ +/////////////////////////////////////////////// +/* Extensions for UAParser.js v2.0 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + MIT License */ +////////////////////////////////////////////// + +const UAParser = require("./ua-parser") + +const Bots = Object.freeze({ + browser : [ + [/((?:google|bing|msn|facebook)bot(?:\-[imagevdo]{5})?|bingpreview)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']] + ] +}); + +const Emails = Object.freeze({ + browser : [ + [/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'email']] + ] +}); + +const Tools = Object.freeze({ + browser : [ + [/(wget|curl|lynx)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'tool']] + ] +}); + +module.exports = { + Bots, + Emails, + Tools +} \ No newline at end of file diff --git a/src/ua-parser-extension.mjs b/src/ua-parser-extension.mjs new file mode 100644 index 0000000..a6b4032 --- /dev/null +++ b/src/ua-parser-extension.mjs @@ -0,0 +1,36 @@ +// Generated ESM version of UAParser.js extensions +// DO NOT EDIT THIS FILE! +// Source: /src/ua-parser-extension.js + +/////////////////////////////////////////////// +/* Extensions for UAParser.js v2.0 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + MIT License */ +////////////////////////////////////////////// + +const UAParser = require("./ua-parser") + +const Bots = Object.freeze({ + browser : [ + [/((?:google|bing|msn|facebook)bot(?:\-[imagevdo]{5})?|bingpreview)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']] + ] +}); + +const Emails = Object.freeze({ + browser : [ + [/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'email']] + ] +}); + +const Tools = Object.freeze({ + browser : [ + [/(wget|curl|lynx)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'tool']] + ] +}); + +export { + Bots, + Emails, + Tools +} \ No newline at end of file diff --git a/test/test-extension.js b/test/test-extension.js new file mode 100644 index 0000000..bbe2fd2 --- /dev/null +++ b/test/test-extension.js @@ -0,0 +1,35 @@ +const assert = require('assert'); +const safeRegex = require('safe-regex'); +const UAParser = require('ua-parser-js'); +const { Bots, Emails, Tools } = require('ua-parser-js/extensions'); + +describe('Bots', () => { + it('Can detect bots', () => { + const googleBot = 'Googlebot-Video/1.0'; + const msnBot = 'msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)'; + const bingPreview = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b'; + const opera = 'Opera/8.5 (Macintosh; PPC Mac OS X; U; en)'; + const wget = 'Wget/1.21.1'; + const facebookBot = 'Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/)'; + const outlook = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.9126; Microsoft Outlook 16.0.9126; ms-office; MSOffice 16)'; + const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0'; + + const botParser = new UAParser(Bots); + assert.deepEqual(botParser.setUA(googleBot).getBrowser(), {name: "Googlebot-Video", version: "1.0", major: "1", type: "bot"}); + assert.deepEqual(botParser.setUA(msnBot).getBrowser(), {name: "msnbot-media", version: "1.1", major: "1", type: "bot"}); + assert.deepEqual(botParser.setUA(bingPreview).getBrowser(), {name: "BingPreview", version: "1.0b", major: "1", type: "bot"}); + assert.deepEqual(botParser.setUA(opera).getBrowser(), {name: "Opera", version: "8.5", major: "8"}); + + // try merging Bots & Tools + const botsAndTools = { browser : [...Bots.browser, ...Tools.browser]}; + const botolParser = new UAParser(botsAndTools); + assert.deepEqual(botolParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"tool"}); + assert.deepEqual(botolParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"bot"}); + + const emailParser = new UAParser(Emails); + assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: "Microsoft Outlook", version: "16.0.9126", major: "16", type: "email"}); + assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: "Thunderbird", version: "78.13.0", major: "78", type: "email"}); + }); +}); + +// TODO : check for safe-regex \ No newline at end of file