[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: juliangruber\npatreon: juliangruber\ncustom: \"https://paypal.me/julianpetergruber\""
  },
  {
    "path": ".github/SECURITY.md",
    "content": "## Security contact information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure."
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"node\"\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "\n# is-mobile\n\nCheck if mobile browser, based on useragent string.\n\n[![Build Status](https://travis-ci.org/juliangruber/is-mobile.svg?branch=master)](https://travis-ci.org/juliangruber/is-mobile)\n\n## Example\n\n```js\nvar mobile = require('is-mobile');\n\nconsole.log(mobile());\n// => false\n```\n\n## API\n\n### mobile({ [ua], [tablet], [featureDetect] })\n\nReturns true if a mobile browser is being used.\n\nIf you don't specify `opts.ua` it will use `navigator.userAgent`.\n\nTo add support for tablets, set `tablet: true`.\n\nTo enable feature detection (i.e. namely for iPad with iOS 13), set `featureDetect: true` and `tablet: true`. This will only work in browser environments.\n\n`opts.ua` can also be an instance of a [node.js http request](http://nodejs.org/api/http.html#http_http_incomingmessage), in which\ncase it will read the user agent header.\n\nExample:\n\n```js\nvar http = require('http');\nvar mobile = require('is-mobile');\n\nvar server = http.createServer(function (req, res) {\n  res.end(mobile({ ua: req }));\n});\n\nserver.listen(8000);\n```\n\n## Installation\n\nWith [npm](https://npmjs.org) do:\n\n```bash\nnpm install is-mobile\n```\n\nBundle for the browser with\n[browserify](https://github.com/substack/node-browserify).\n\n## Kudos\n\nTaken from [detectmobilebrowsers.com](http://detectmobilebrowsers.com/).\n\nArmv7l support added by [@antongolub](https://github.com/antongolub).\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "index.d.ts",
    "content": "interface HttpRequestHeadersInterfaceMock {\n    [id: string]: string | string[] | undefined\n}\n\ninterface HttpRequestInterfaceMock {\n    headers: HttpRequestHeadersInterfaceMock,\n\n    [id: string]: any,\n}\n\nexport interface IsMobileOptions\n{\n    ua?: string | HttpRequestInterfaceMock\n    tablet?: boolean\n    featureDetect?: boolean\n}\n\nexport declare function isMobile(opts?:IsMobileOptions): boolean;\nexport default isMobile;\n"
  },
  {
    "path": "index.js",
    "content": "'use strict'\n\nmodule.exports = isMobile\nmodule.exports.isMobile = isMobile\nmodule.exports.default = isMobile\n\nconst mobileRE = /(android|bb\\d+|meego).+mobile|armv7l|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|redmi|series[46]0|samsungbrowser.*mobile|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i\nconst notMobileRE = /CrOS/\n\nconst tabletRE = /android|ipad|playbook|silk/i\n\nfunction isMobile (opts) {\n  if (!opts) opts = {}\n  let ua = opts.ua\n  if (!ua && typeof navigator !== 'undefined') ua = navigator.userAgent\n  if (ua && ua.headers && typeof ua.headers['user-agent'] === 'string') {\n    ua = ua.headers['user-agent']\n  }\n  if (typeof ua !== 'string') return false\n\n  let result =\n    (mobileRE.test(ua) && !notMobileRE.test(ua)) ||\n    (!!opts.tablet && tabletRE.test(ua))\n\n  if (\n    !result &&\n    opts.tablet &&\n    opts.featureDetect &&\n    navigator &&\n    navigator.maxTouchPoints > 1 &&\n    ua.indexOf('Macintosh') !== -1 &&\n    ua.indexOf('Safari') !== -1\n  ) {\n    result = true\n  }\n\n  return result\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"is-mobile\",\n  \"description\": \"Check if mobile browser.\",\n  \"version\": \"5.0.0\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/juliangruber/is-mobile.git\"\n  },\n  \"homepage\": \"https://github.com/juliangruber/is-mobile\",\n  \"main\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"scripts\": {\n    \"release\": \"np\",\n    \"test\": \"prettier-standard '**/*.js' && standard && npm run test:unit\",\n    \"test:unit\": \"node--test\"\n  },\n  \"devDependencies\": {\n    \"np\": \"^8.0.4\",\n    \"prettier-standard\": \"^16.4.1\",\n    \"standard\": \"^16.0.4\",\n    \"test\": \"^3.0.0\",\n    \"user-agents\": \"^1.0.845\"\n  },\n  \"keywords\": [\n    \"mobile\",\n    \"desktop\",\n    \"check\",\n    \"browser\"\n  ],\n  \"author\": {\n    \"name\": \"Julian Gruber\",\n    \"email\": \"julian@juliangruber.com\",\n    \"url\": \"http://juliangruber.com\"\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "tea.yaml",
    "content": "# https://tea.xyz/what-is-this-file\n---\nversion: 1.0.0\ncodeOwners:\n  - '0xE7DEE1B8Bb97C3065850Cf582D6DED57C6009587'\nquorum: 1\n"
  },
  {
    "path": "test.js",
    "content": "'use strict'\n\nconst assert = require('assert')\nconst test = require('test')\nconst UserAgent = require('user-agents')\nconst isMobile = require('./')\n\nconst iphone =\n  'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3'\nconst chrome =\n  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36'\nconst ffos = 'Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0'\nconst ipad =\n  'Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1'\nconst ios13ipad =\n  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'\nconst ios13ipadpro =\n  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15'\nconst samsung =\n  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.0 Chrome/92.0.4515.166 Safari/537.36'\nconst samsungMobile =\n  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.0 Chrome/92.0.4515.166 Mobile Safari/537.36'\nconst chromeOS =\n  'Mozilla/5.0 (X11; CrOS armv7l 12105.100.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.144 Safari/537.36'\nconst redmiMobile =\n  'HashKey/1.20.0 (Redmi K30; Android ) Language/zh Theme/light ScreenWidth/392 ScreenHeight/856'\n\ntest('is mobile', function () {\n  assert(isMobile({ ua: iphone }))\n  assert(isMobile({ ua: ffos }))\n  assert(!isMobile({ ua: ipad }))\n  assert(isMobile({ ua: ipad, tablet: true }))\n  assert(isMobile({ ua: { headers: { 'user-agent': iphone } } }))\n  assert(!isMobile({ ua: chrome }))\n  assert(!isMobile({ ua: { headers: { 'user-agent': chrome } } }))\n  assert(!isMobile())\n  assert(!isMobile({ ua: { headers: null } }))\n  assert(!isMobile({ ua: { headers: { 'user-agent': null } } }))\n  assert(!isMobile({ ua: samsung }))\n  assert(isMobile({ ua: samsungMobile }))\n  assert(isMobile({ ua: redmiMobile }))\n  assert(!isMobile(chromeOS))\n  assert(!isMobile(chromeOS, { tablet: true }))\n\n  global.navigator = {}\n\n  global.navigator.userAgent = iphone\n  assert(isMobile())\n  assert(isMobile({ tablet: true }))\n\n  global.navigator.userAgent = chrome\n  assert(!isMobile())\n  assert(!isMobile({ tablet: true }))\n\n  global.navigator.userAgent = ipad\n  assert(!isMobile())\n  assert(isMobile({ tablet: true }))\n\n  global.navigator = { maxTouchPoints: 5 }\n  assert(isMobile({ ua: ios13ipad, tablet: true, featureDetect: true }))\n  assert(isMobile({ ua: ios13ipadpro, tablet: true, featureDetect: true }))\n})\n\ntest('ua-bruteforce', function () {\n  const limit = 300\n  const checks = [\n    { deviceCategory: 'mobile', result: true },\n    { deviceCategory: 'tablet', result: true, tablet: true },\n    { deviceCategory: 'desktop', result: false }\n  ]\n  const testCases = checks.reduce(\n    (cases, { deviceCategory, result, tablet }) => {\n      // The same user-agent string belongs to both `desktop` and `mobile` type entries. No chance to detect `deviceType` properly.\n      // https://github.com/intoli/user-agents/blob/867e318bc00880ae00437e5e8efaa8e5e7ac0696/src/user-agents.json.gz\n      // user-agents v1.0.843\n      const exclude =\n        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'\n      const ua = new UserAgent([\n        ({ userAgent }) => userAgent !== exclude,\n        { deviceCategory }\n      ])\n\n      return [\n        ...cases,\n        ...new Array(limit).fill().map(() => ({\n          ua: ua.random().toString(),\n          result,\n          tablet\n        }))\n      ]\n    },\n    []\n  )\n\n  testCases.forEach(({ ua, result, tablet }) => {\n    test(ua, () => {\n      assert.strictEqual(isMobile({ ua, tablet }), result)\n    })\n  })\n})\n"
  }
]