[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Library version**\nWhich version of the library that you use, eg: v0.7.35 or v2.0.0-alpha.3\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen, or what's referred in the docs https://docs.uaparser.dev/\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\nFor issues related to detection results, you can send the screenshots of the demo section at https://uaparser.dev/#demo to confirm.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. iOS]\n - Browser [e.g. chrome, safari]\n - Version [e.g. 22]\n\n**Smartphone (please complete the following information):**\n - Device: [e.g. iPhone6]\n - OS: [e.g. iOS8.1]\n - Browser [e.g. stock browser, safari]\n - Version [e.g. 22]\n\n**Additional context**\nAdd any other context about the problem here."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/pull_request_template.md",
    "content": "- [ ] I have read and accept the [Contributor License Agreement (CLA)](https://gist.github.com/faisalman/2ed16621ebb544157eba85a7f7381417) Document and I hereby sign the CLA"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "# Prerequisites\n\n- [ ] I have read and follow the [contributing](https://github.com/faisalman/ua-parser-js/blob/master/CONTRIBUTING.md) guidelines\n- [ ] I have read and accept the [Contributor License Agreement (CLA)](https://gist.github.com/faisalman/2ed16621ebb544157eba85a7f7381417) Document and I hereby sign the CLA\n\n# Type of Change\n\nBug fix, feature, docs update, ...\n\n# Description\n\nPlease include a summary of the change (current behavior vs new behavior), which issue is fixed (you can also link to an open issue here), and why this change is necessary.\n\n# Test\n\nPlease describe the tests that you ran to verify your changes.\n\n# Impact\n\nDoes this PR introduce a breaking change? What changes might users need to make due to this PR?\n\n# Other Info"
  },
  {
    "path": ".github/funding.yml",
    "content": "# These are supported funding model platforms\n\ngithub: faisalman\npatreon: # Replace with a single Patreon username\nopen_collective: ua-parser-js\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: ['https://www.paypal.me/faisalman/', 'https://uaparser.dev']\n"
  },
  {
    "path": ".github/workflows/analysis-codeql.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: CodeQL Analysis\n\non:\n  push:\n    branches: [ \"master\"]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ \"master\" ]\n  schedule:\n    - cron: '15 6 * * 0'\n\npermissions: read-all\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Use only 'java' to analyze code written in Java, Kotlin or both\n        # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v3\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n\n        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n        # queries: security-extended,security-and-quality\n\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, Go, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    # - name: Autobuild\n    #  uses: github/codeql-action/autobuild@v2\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n    #   If the Autobuild fails above, remove it and uncomment the following three lines.\n    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n    # - run: |\n    #     echo \"Run, Build Application using script\"\n    #     ./location_of_script_within_repo/buildscript.sh\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n      with:\n        category: \"/language:${{matrix.language}}\"\n"
  },
  {
    "path": ".github/workflows/analysis-dependency.yml",
    "content": "# Dependency Review Action\n#\n# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.\n#\n# Source repository: https://github.com/actions/dependency-review-action\n# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement\nname: Dependency Analysis\non: [pull_request]\n\npermissions:\n  contents: read\n\njobs:\n  dependency-review:\n    runs-on: ubuntu-latest\n    steps:\n      - name: 'Checkout Repository'\n        uses: actions/checkout@v3\n      - name: 'Dependency Review'\n        uses: actions/dependency-review-action@v2\n"
  },
  {
    "path": ".github/workflows/analysis-scorecard.yml",
    "content": "# This workflow uses actions that are not certified by GitHub. They are provided\n# by a third-party and are governed by separate terms of service, privacy\n# policy, and support documentation.\n\nname: OpenSSF's Scorecard Analysis\non:\n  # For Branch-Protection check. Only the default branch is supported. See\n  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection\n  branch_protection_rule:\n  # To guarantee Maintained check is occasionally updated. See\n  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained\n  schedule:\n    - cron: '45 2 * * 4'\n  push:\n    branches: [ \"master\" ]\n\n# Declare default permissions as read only.\npermissions: read-all\n\njobs:\n  analysis:\n    name: Scorecard analysis\n    runs-on: ubuntu-latest\n    permissions:\n      # Needed to upload the results to code-scanning dashboard.\n      security-events: write\n      # Needed to publish results and get a badge (see publish_results below).\n      id-token: write\n      # Uncomment the permissions below if installing in a private repository.\n      # contents: read\n      # actions: read\n\n    steps:\n      - name: \"Checkout code\"\n        uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0\n        with:\n          persist-credentials: false\n\n      - name: \"Run analysis\"\n        uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2\n        with:\n          results_file: results.sarif\n          results_format: sarif\n          # (Optional) \"write\" PAT token. Uncomment the `repo_token` line below if:\n          # - you want to enable the Branch-Protection check on a *public* repository, or\n          # - you are installing Scorecard on a *private* repository\n          # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.\n          repo_token: ${{ secrets.SCORECARD_TOKEN }}\n\n          # Public repositories:\n          #   - Publish results to OpenSSF REST API for easy access by consumers\n          #   - Allows the repository to include the Scorecard badge.\n          #   - See https://github.com/ossf/scorecard-action#publishing-results.\n          # For private repositories:\n          #   - `publish_results` will always be set to `false`, regardless\n          #     of the value entered here.\n          publish_results: true\n\n      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF\n      # format to the repository Actions tab.\n      - name: \"Upload artifact\"\n        uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0\n        with:\n          name: SARIF file\n          path: results.sarif\n          retention-days: 5\n\n      # Upload the results to GitHub's code scanning dashboard.\n      - name: \"Upload to code-scanning\"\n        uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4\n        with:\n          sarif_file: results.sarif\n"
  },
  {
    "path": ".github/workflows/publish-github-packages.yml",
    "content": "name: Publish to GitHub Package\n\non:\n  release:\n    types: [published]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-node@v3\n        with:\n          node-version: '18.x'\n          registry-url: https://npm.pkg.github.com/\n      - run: npm ci\n      - run: npm publish\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}"
  },
  {
    "path": ".github/workflows/publish-npm-packages.yml",
    "content": "name: Publish to NPM\n\non:\n release:\n   types: [published]\n\njobs:\n build:\n   runs-on: ubuntu-latest\n   permissions:\n     contents: read\n     id-token: write\n   steps:\n     - uses: actions/checkout@v3\n     - uses: actions/setup-node@v3\n       with:\n         node-version: '18.x'\n         registry-url: 'https://registry.npmjs.org'\n     - run: npm install -g npm\n     - run: npm ci\n     - run: npm publish --provenance --access public\n       env:\n         NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}"
  },
  {
    "path": ".github/workflows/test-ci.yml",
    "content": "name: UAParser.js CI-Test\n\non: [push, pull_request]\n\npermissions:\n  contents: read\n\njobs:\n  run-test:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        arch: [amd64]\n        node-version: ['22.13', 'lts/*']\n        include:\n          - arch: ppc64le\n            node-version: 20\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with: \n          node-version:  ${{ matrix.node-version }}\n      - name: Run the test\n        run: |\n          echo \"Running on ubuntu-latest-${{ matrix.arch }} with node version set as ${{ matrix.node-version }}\"\n          npm ci\n          npx playwright install --with-deps\n          npm test\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\nnpm-debug.log\nplaywright-report/\ntest-results/\n\n### vim ###\n.*.s[a-w][a-z]\n*.un~\nSession.vim\n.netrwhist\n*~\n.versions\n\n### editors ###\n.vscode\n.idea\n*.sublime-*\n\n### OSX ###\n.DS_Store\n.AppleDouble\n.LSOverride\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear on external disk\n.Spotlight-V100\n.Trashes\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# UAParser.js Changelog\n\n## Migrating from v1 to v2\n\n### What's Breaking:\n\n- **Licensing Changes:**\n  - UAParser.js is now licensed under AGPLv3 for open-source use, with PRO Licenses available for commercial/proprietary use\n\n- **Browser Detection on Mobile Devices:**\n    - `\"Chrome\"` => `\"Mobile Chrome\"`\n    - `\"Firefox\"` => `\"Mobile Firefox\"`\n\n- **OS Detection:**\n    - `\"Mac OS\"` => `\"macOS\"`\n    - `\"Chromium OS\"` => `\"Chrome OS\"`\n\n### What's New:\n\n- **Support for ES Modules & TypeScript:**\n  - Import directly as an ES module with TypeScript support: `import { UAParser } from 'ua-parser-js'`\n\n- **Support for Custom/Predefined Extensions:**\n  - Pass custom regexes or predefined extensions as a list to `UAParser()`\n\n- **Support for CLI Processing:**\n  - Directly parse user-agent strings from the command line:\n    `npx ua-parser-js \"<User-Agent>\"`\n  - Process batch data from files: \n    `npx ua-parser-js --input-file=log.txt >> result.json` or\n    `npx ua-parser-js --input-file=log.txt --output-file=result.json`\n\n- **Enhanced Detection with Client Hints:**\n  - `withClientHints()`: Improves detection accuracy by leveraging client hints\n\n- **Enhanced Detection with Feature Detection:**\n  - `withFeatureCheck()`: Refines detection results using feature detection\n\n- **Simple Comparison for Detection Results:**\n  - `is()`: Enables easy comparison checks against the detection result\n\n- **Detailed Result Output:**\n  - `toString()`: Returns the detection result in form of a full-name string\n\n- **New Device Type:**\n  - Added `xr` to identify AR/VR devices\n\n- **New Browser Property:**\n  - Added `browser.type` to identify additional browser types:\n    - `crawler`, `cli`, `email`, `fetcher`, `inapp`, `library`, `mediaplayer`\n\n- **New Submodules:**\n  - **`'ua-parser-js/enums'`**: Provides constants for these specific properties:\n    - `browser.name`, `browser.type`, `cpu.architecture`, `device.type`, `device.vendor`, `engine.name`, `os.name`\n\n  - **`'ua-parser-js/extensions'`**: Predefined extensions for various use cases:\n    - `Bots`, `Crawlers`, `CLIs`, `Emails`, `ExtraDevices`, `Fetchers`, `InApps`, `Libraries`, `Mediaplayers`, `Vehicles`\n\n  - **`'ua-parser-js/helpers'`**: Provides utility methods to extend detection functionality:\n    - `isFrozenUA()`: Checks if the user-agent matches a frozen/reduced user-agent pattern\n\n  - **`'ua-parser-js/bot-detection'`**:\n    - `isAIAssistant()`: Checks if the user-agent is an AI assistant\n    - `isAICrawler()`: Checks if the user-agent is an AI crawler\n    - `isBot()`: Checks if the user-agent is a bot\n\n  - **`'ua-parser-js/browser-detection'`**:\n    - `isChromeFamily()`: Checks if the browser is Chrome-based (uses Blink engine) — e.g., New Opera, New Edge, Vivaldi, Brave, Arc, etc.\n    - `isElectron()`: Detects if current window is running within Electron\n    - `isFromEU()`: Detects if current browser's timezone is from an EU country\n    - `isStandalonePWA()`: Detects if current window is a standalone PWA\n\n  - **`'ua-parser-js/device-detection'`**:\n    - `getDeviceVendor()`: Guesses the device vendor based on its model name\n    - `isAppleSilicon()`: Detects Apple Silicon device properties\n\n--- \n\n## Version 2.0.9\n- Restore icons directory\n- Add new browser: Aloha Browser, Avira Secure Browser, Lighthouse, Luakit, Norton Private Browser\n- Add new OS: Vega OS\n- Improve OS detection: watchOS\n- `extensions` submodule:\n    - Add new crawler: atlassian-bot, Cloudflare-AutoRAG, Google-NotebookLM, SemrushBot-SWA\n    - Add new fetcher: FlipboardProxy\n\n## Version 2.0.8\n\n- Resolve syntax error related to import renaming in ESM build\n- Add new browser: HiBrowser, Opera Neon\n- Add new engine: Dillo\n- Improve browser detection: Brave, TikTok\n- Improve device detection: OnePlus\n- Improve OS detection: Firefox OS\n- `extensions` submodule:\n    - Add new CLI: PowerShell\n    - Add new email: Alpine, Android, AquaMail, Balsa, Barca, Canary, Claws Mail, eM Client, Eudora, FairEmail, Geary, Gnus, Horde::IMP, Lotus-Notes, IncrediMail, K-9 Mail, Mailbird, MailMate, Mailspring, Mutt, Newton, Nine, NylasMail, Outlook-Express, Pegasus Mail, PocoMail, Postbox, ProtonMail Bridge, Quala, R2Mail2, Rainloop, Roundcube Webmail, SamsungEmail, Spicebird, SquirrelMail, Sylpheed, The Bat!, Trojita, Turnpike, tutanota-desktop, Wanderlust, Windows-Live-Mail\n    - Add new library: http.rb, Jetty, ocaml-cohttp\n- `helpers` submodule:\n    - Add new method: `getOutlookEdition()` to map Outlook versions to their marketing editions\n\n## Version 2.0.7\n\n- Add support for chaining `withClientHints()` & `withFeatureCheck()`\n- Add new browser: Atlas, Steam\n- Add new device vendor: Anbernic, Logitech, Valve\n- Improve device detection: Xiaomi\n- Improve OS detection: iOS\n- Split `helpers` submodule into several new submodules:\n    - `bot-detection`:\n        - `isAIAssistant()`\n        - `isAICrawler()`\n        - `isBot()`\n    - `browser-detection`\n        - `isChromeFamily()`\n        - `isElectron()`\n        - `isFromEU()`\n        - `isStandalonePWA()`\n    - `device-detection`\n        - `getDeviceVendor()`\n        - `isAppleSilicon()`\n- Update `extensions` submodule:\n    - Add new fetcher: Nova Act\n    - Add new library: Bun, Dart, Deno, hackney, Node.js, rest-client, undici\n\n## Version 2.0.6\n- Add new CLI feature: processing batch user-agent data from file and output as JSON\n- Fix `setUA()`: trim leading space from user-agent string input\n- Replace `undici` dependency with node's internal `Headers`\n- Add new browser: Bing, Qwant\n- Add new device vendor: Hisense, Wiko\n- Improve browser detection: Mozilla, Pale Moon\n- Improve CPU detection: 68k\n- Improve device detection: Apple, BlackBerry, Huawei, Nokia, Xiaomi\n- Improve OS detection: iOS 26\n- `extensions` submodule:\n    - Add new fetcher: Discordbot, KeybaseBot, Slackbot, Slackbot-LinkExpanding, Slack-ImgProxy, Twitterbot\n    - Add new crawler: Qwantbot-news, SurdotlyBot, SwiftBot\n\n## Version 2.0.5\n\n- Add new browser: Zalo\n- Add new CPU arch: alpha\n- Add new device vendor: Philips\n- Improve device detection: Pico\n- Fix parsing error on pages with modified Array prototypes\n- Improve type declarations:\n    - Replace `node-fetch` dependency with `undici`\n    - Replace hardcoded string values with enum from `enum` submodule\n- `enums` submodule:\n    - Add `Extension` enum for `extensions` submodule\n    - Type declaration file now automatically generated using build script\n    - Naming adjustments:\n        - `Browser` => `BrowserName`\n        - `CPU` => `CPUArch`\n        - `Device` => `DeviceType`\n        - `Vendor` => `DeviceVendor`\n        - `Engine` => `EngineName`\n        - `OS` => `OSName`\n- `extensions` submodule:\n    - Add new crawlers: \n        APIs-Google, Algolia Crawler, Algolia Crawler Renderscript, Baidu-ADS, BLEXBot, botify, Bravebot, Claude-Web, cohere-training-data-crawler, contxbot, Cotoyogi, Coveobot, CriteoBot, DeepSeekBot, DuckDuckGo-Favicons-Bot, Elastic, FirecrawlAgent, Freespoke, Google-CloudVertexBot, HuggingFace-Bot, Kagibot, Kangaroo Bot, marginalia, msnbot, OnCrawl, Replicate-Bot, RunPod-Bot, SBIntuitionsBot, SeekportBot, Siteimprove, Sogou Pic Spider, TikTokSpider, TwinAgent, v0bot, webzio, Webzio-Extended, xAI-Bot, YandexAccessibilityBot, YandexAdditionalBot, YandexAdNet, YandexBot MirrorDetector, YandexBlogs, YandexComBot, YandexFavicons, YandexImageResizer, YandexImages, YandexMarket, YandexMetrika, YandexMedia, YandexMobileBot, YandexMobileScreenShotBot, YandexNews, YandexOntoDB, YandexOntoDBAPI, YandexPartner, YandexRCA, YandexRenderResourcesBot, YandexScreenshotBot, YandexSpravBot, YandexTracker, YandexVertis, YandexVerticals, YandexVideo, YandexVideoParser, YandexWebmaster, YepBot, ZumBot\n    - Add new fetchers: \n        Asana, bitlybot, Blueno, BufferLinkPreviewBot, Chrome-Lighthouse, Gemini-Deep-Research, HubSpot Page Fetcher, kakaotalk-scrap, vercel-favicon-bot, vercel-screenshot-bot, vercelflags, verceltracing, YaDirectFetcher, YandexCalendar, YandexDirect, YandexDirectDyn, YandexForDomain, YandexPagechecker, YandexSearchShop, YandexSitelinks, YandexUserproxy\n- `helpers` submodule:\n    - Add some crawler to `isAIBot()`: \n        Bravebot, cohere-training-data-crawler, FirecrawlAgent, HuggingFace-Bot, Kangaroo Bot, PanguBot, Replicate-Bot, RunPod-Bot, TikTokSpider, Together-Bot, v0bot, xAI-Bot\n\n## Version 2.0.4\n\n- Add new browser: Edge WebView, Edge WebView2\n- Add new device vendor: Lava, Retroid, Vizio\n- Add new OS: ArcaOS, Knoppix, Xubuntu, Windows CE, Windows RT\n- Improve device detection: Google Pixel & Pixelbook Series, HMD, Infinix, LG WebOS TV, Motorola, Nothing, OnePlus, Sony, Tecno\n- Improve OS detection: AIX, Arch, Fuchsia, Haiku, HarmonyOS, Mint, MorphOS, Solaris, Windows\n- Improve `withClientHints()` browser naming adjustments: `Microsoft Edge WebView2` => `Edge WebView2`\n- Identify device that uses Firefox Reality / Wolvic as `xr`\n- Identify device with large screen as `smarttv`\n- Identify Windows CE & Windows RT as distinct OS variants\n- `extensions` submodule:\n    - Remove lookbehind assertion to ensure regex compatibility\n    - Add new crawlers: ChatGLM, Daum, iAskBot, Onespot, Qwantbot, Startpage\n    - Add new emails: Apple's Mail, DaumMail, Polymail, ProtonMail, SparkDesktop, Zimbra, ZohoMail-Desktop\n    - Add new fetchers: Iframely, MistralAI-User, Perplexity-User\n    - Add new inApps: Discord, Evernote, Figma, Flipboard, Mattermost, Notion, Postman, Rambox, Rocket.Chat, Microsoft Teams, TikTok Lite, VS Code\n    - Add new libraries: AdobeAIR, aiohttp, nutch, httpx, urllib3\n- `enum` submodule:\n    - Fix mistakenly placed `BLU` categorized as browser name instead of device vendor\n\n## Version 2.0.3\n\n- Add new browser: Dooble, Ecosia, LG Browser, Otter, qutebrowser, Surf\n- Add new device: BLU, Facebook Portal TV\n- Improve device detection: Archos, LG, Meta Quest\n- Remove jazzer.js fuzz test\n- Improve `withClientHints()`:\n    - Browser naming adjustments:\n        - `HuaweiBrowser` => `Huawei Browser`\n        - `Miui Browser` => `MIUI Browser`\n        - `OperaMobile` => `Opera Mobi`\n        - `YaBrowser` => `Yandex`\n- `extensions` submodule:\n    - Add new Crawler: AdIdxBot, Linespider, LinkedInBot, OpenAI Image Downloader, SemrushBot, Yahoo! Slurp\n    - Add new Fetcher: Better Uptime Bot, Google-PageRenderer, GoogleImageProxy, MicrosoftPreview, Snap URL Preview, SkypeUriPreview, TelegramBot\n    - Add new Vehicles: BMW, Jeep\n    - Add OS detection of WhatsApp user-agent\n\n## Version 2.0.2\n\n- Fix TypeScript dependency issue\n\n## Version 2.0.1\n\n- Add new browser: Ladybird, Daum\n- Add new device: Apple HomePod\n- Add new device vendor: HMD\n- Add new OS: Ubuntu Touch, Windows IoT\n- Improve CPU detection: ARM, x86\n- Improve device detection: Lenovo, Nokia, Nvidia, Xiaomi\n    - Tablet: Google, Honor, Huawei, Infinix, Nokia, OnePlus, Xiaomi\n    - Wearable: Asus, Google, LG, Motorola, OnePlus, Oppo, Samsung, Sony\n    - Smart-TV: Xiaomi, unidentified vendors\n    - Improve detection for unknown VR devices\n    - Improve device model detection for Generic devices\n- Improve OS detection: Linux, Symbian\n- Improve TypeScript definitions for Headers\n- Improve `withClientHints()`:\n    - `engine.version` also get updated\n    - Infer `device.vendor` & `device.type` by guessing from `device.model`\n    - Browser naming adjustments:\n        - `Google Chrome` => `Chrome`\n        - `Microsoft Edge` => `Edge`\n        - `Android WebView` => `Chrome WebView`\n        - `HeadlessChrome` => `Chrome Headless`\n- `enums` submodule:\n    - Add TypeScript definitions\n- `extensions` submodule:\n    - Add new list: \n        - `Vehicles`: BYD, Rivian, Volvo\n    - Add new Fetcher: Bluesky\n    - Add new Library: Apache-HttpClient, go-http-client, got, GuzzleHttp, Java-http-client, libwww-perl, lua-resty-http, Needle, OkHttp, node-fetch, PHP-SOAP, PostmanRuntime, superagent\n\n## Version 2.0.0\n\n- `ua-parser-js/extensions` submodule:\n    - Add new CLI: ELinks, HTTPie\n    - Add new crawler: AI2Bot, aiHitBot, anthropic-ai, Diffbot, ImagesiftBot, magpie-crawler, Omgilibot, Screaming Frog SEO Spider, Seznambot, Teoma, Timpibot, VelenPublicWebCrawler, Webzio-Extended, YouBot\n    - Add new email: Airmail, BlueMail, eMClient, NaverMailApp, Sparrow, Yahoo\n    - Add new fetcher: cohere-ai, Vercelbot\n    - Add new library: java, python-urllib, python-requests\n- `ua-parser-js/helpers` submodule:\n    - Add new method `isAIBot()`: Checks if the user-agent is an AI bot\n\n## Version 2.0.0-rc.3\n\n- Add support for Headers object\n- Add new device: Advan, Cat, Energizer, Honor, IMO, Micromax, Smartfren\n- Add new engine: Servo\n- `ua-parser-js/extensions` submodule:\n    - Breaking change: rename `module` to `library`\n    - Add new email clients: Evolution, KMail, Kontact\n    - Add new bots: 360Spider, Archive.org Bots, CCBot, DataForSeoBot, DuckAssistBot, Exabot, Google Bots, Meta Bots, MojeekBot, PerplexityBot, PetalBot, TurnitinBot, Yeti, YisouSpider\n\n## Version 2.0.0-rc.2\n\n- Fix incorrect import path in ESM files\n- Add new browser: 115, SlimBoat, Slimjet, LibreWolf\n- Improve browser detection: 2345, 360, Dragon, Iron, Maxthon\n- `ua-parser-js/enums` submodule:\n    - Add Chromecast OS variants: Android/Fuchsia/Linux/SmartSpeaker\n- `ua-parser-js/helpers` submodule:\n    - Add new method: `isBot()` to check if the browser is identified as a bot\n\n## Version 2.0.0-rc.1\n\n- Fix Python Request mistakenly identified as Meta Quest\n- Add new browser: Helio\n- Add new device: itel, Nothing, Pico, TCL\n- Add new engine: ArkWeb\n- Add new OS: OpenHarmony, Pico\n- Improve browser detection: Quark\n- Improve device detection: Xiaomi, Amazon Echo Show, Google Chromecast, Samsung Galaxy Watch\n- `ua-parser-js/helpers` submodule:\n    - Add new method: \n        - `getDeviceVendor()` to guess for a device vendor based on its model name\n        - `isElectron()` to check if current window is running inside Electron\n        - `isFromEU()` to check if current window is from an EU (European Union) country\n        - `isStandalonePWA()` to check if current window is a standalone PWA\n    - Rename `isChromiumBased()` to `isChromeFamily()`\n    - Update `isAppleSilicon()` to also checks for WebGL renderer info\n- `ua-parser-js/extensions` submodule:\n    - Restore `Bots` as a compilation of all these browser types: `cli`, `crawler`, `fetcher`, and `library`\n\n## Version 2.0.0-beta.3\n\n- Breaking:\n  - AR/VR devices moved to new device type: `xr`\n  - New property in `browser`: `type`\n- New features:\n  - Parse directly from command line using `npx ua-parser-js`\n  - Extensions can be passed as a list to `UAParser()`\n- Add new browser: Pico Browser, Twitter, Wolvic\n- Improve browser detection: DuckDuckGo, ICEBrowser, Klar, QQ, Sleipnir\n- Improve device detection: Oculus Quest & Oppo Pad\n- Update latest client hints spec: `formFactor` -> `formFactors`\n- In `ua-parser-js/extensions` submodule, `bots` divided into `crawler` / `fetcher` \n\n## Version 2.0.0-beta.2\n\n- Increase UA_MAX_LENGTH to 500\n- Add TypeScript declaration file in `ua-parser-js/extensions` submodule\n- Improve TypeScript module resolution\n- Add new methods in `ua-parser-js/helpers` submodule: `isAppleSilicon()` & `isChromiumBased()`\n- Fix misidentified WebView token as device model\n- Add new browser: Alipay, Klarna, Opera GX, Smart Lenovo Browser, Vivo Browser\n- Rename browser: Avant, Baidu, Samsung Internet, Sogou Explorer, Sogou Mobile, WeChat\n- Improve client-hints detection: Edge, Xbox\n\n## Version 2.0.0-beta.1\n\n- Update Client Hints Form-Factor\n- Provide in-package type definitions\n- Add new device: Ulefone\n- Improve device detection: Realme, Xiaomi Redmi\n\n## Version 2.0.0-alpha.3\n\n- Add `withFeatureCheck()` method\n- Add `isFrozenUA()` method in `ua-parser-js/helpers` submodule\n- Add `MediaPlayers` & `Modules` in `ua-parser-js/extensions` submodule\n- Fix issue with ESM import\n\n## Version 2.0.0-alpha.2\n\n- Fix browser result always returning Chromium when using withClientHints()\n- Fix infinite-loop when await-ing withClientHints() in non-client-hints browser\n\n## Version 2.0.0-alpha.1\n\n- Initial work on new major version\n\n---\n\n## Version 0.7.41 / 1.0.41\n- Add new browser: Daum, Ladybird\n- Add new device vendor: HMD\n- Add new engine: LibWeb\n- Add new os: Windows IoT, Ubuntu Touch\n- Improve cpu detection: ARM, x86\n- Improve device vendor detection: Apple, Archos, Generic, Google, Honor, Huawei, Infinix, Nvidia, Lenovo, Nokia, OnePlus, Xiaomi\n- Improve device type detection: smarttv, wearables\n- Improve os detection: Linux, Symbian\n\n## Version 0.7.40 / 1.0.40\n- Add new browser: 115, LibreWolf, Slimboat, Slimjet\n- Add new device: Advan, Cat, Energizer, IMO, Micromax, Smartfren\n- Add new engine: ArkWeb, Servo\n- Add new os: OpenHarmony\n- Improve browser detection: 2345, 360, Dragon, Iron, Maxthon\n- Recognize Honor as a separate device vendor from Huawei\n- Fix Python Request mistakenly identified as Meta Quest\n\n## Version 0.7.39 / 1.0.39\n- Add new feature: executable command using `npx ua-parser-js \"[INSERT-UA-HERE]\"`\n- Add new browser: Helio, Pico Browser, Wolvic\n- Add new device vendor: itel, Nothing, TCL\n- Improve browser detection: ICEBrowser, Klar, QQBrowser, Quark, Rekonq, Sleipnir\n- Improve device detection: Xiaomi Pro, Amazon Echo Show, Samsung Galaxy Watch\n- Removed from browser: Viera\n  \n## Version 0.7.38 / 1.0.38\n- Fix error on getOS() when userAgentData.platform is undefined\n- Add new browser: Opera GX, Twitter\n- Improve browser detection: DuckDuckGo\n- Improve device detection: OPPO Pad, Oculus Quest\n\n## Version 0.7.37 / 1.0.37\n- Fix misidentified WebView token as device model\n- Increase UA_MAX_LENGTH to 500\n- Add new browser: Alipay, Klarna, Smart Lenovo Browser, Vivo Browser\n- Add new device: Ulefone\n- Improve device detection: Realme, Xiaomi Redmi\n- Rename browser: Avant, Baidu, Samsung Internet, Sogou Explorer, Sogou Mobile, WeChat\n\n## Version 0.7.36 / 1.0.36\n- Add new browser: Snapchat\n- Add new devices: Infinix, Tecno\n- Improve device detection: Amazon Fire TV, Xiaomi POCO \n- Improve OS detection: iOS\n\n## Version 0.7.35 / 1.0.35\n- Fix result from user-supplied user-agent being altered\n- Add new browser: Heytap, TikTok\n- Add new engine: LibWeb\n- Add new OS: SerenityOS\n- Improve browser detection: Yandex\n- Improve device detection: iPhone, Amazon Echo\n- Improve OS detection: iOS\n\n## Version 0.7.34 / 1.0.34\n- Fix Sharp Mobile detected as Huawei Tablet\n- Fix IE8 bug\n- Add new devices : Kobo e-Reader, Apple Watch, and some new SmartTV devices\n- Add new OS : watchOS\n- Improve browser detection : Kakao, Naver, Brave\n- Improve device detection : Oculus, iPad\n- Improve OS detection : Chrome OS\n- Using navigator.userAgentData as fallback for device.type & os.name\n\n## Version 0.7.33 / 1.0.33\n\n- Add new browser : Cobalt\n- Identify Macintosh as an Apple device\n- Fix ReDoS vulnerability\n\n## Version 0.7.32 / 1.0.32\n\n- Add new browser : DuckDuckGo, Huawei Browser, LinkedIn\n- Add new OS : HarmonyOS\n- Add some Huawei models\n- Add Sharp Aquos TV\n- Improve detection Xiaomi Mi CC9 \n- Fix Sony Xperia 1 III misidentified as Acer tablet\n- Fix Detect Sony BRAVIA as SmartTV \n- Fix Detect Xiaomi Mi TV as SmartTV \n- Fix Detect Galaxy Tab S8 as tablet \n- Fix WeGame mistakenly identified as WeChat\n- Fix included commas in Safari / Mobile Safari version\n- Increase UA_MAX_LENGTH to 350\n\n## Version 0.7.31 / 1.0.2\n\n- Fix OPPO Reno A5 incorrect detection\n- Fix TypeError Bug\n- Use AST to extract regexes and verify them with safe-regex\n\n## Version 0.7.30 / 1.0.1\n\n- Add new browser : Obigo, UP.Browser, Klar\n- Add new device : Oculus, Roku\n- Add new OS: Maemo, HP-UX, Android-x86, Deepin, elementary OS, GhostBSD, Linspire, Manjaro, Sabayon\n- Improve detection for Sony Xperia 1ii, LG Android TV, and some more devices\n- Improve detection for ARM64 CPU\n- Improve detection for Windows Mobile, Netscape, Mac on PowerPC\n- Categorize PDA as mobile\n- Fix Sharp devices misjudged as Huawei\n- Fix trailing comma for ES3 compatibility\n- Some code refactor\n\n## Version 0.7 / 1.0\n\nVersion 1.0.x is basically the equivalent of version 0.7.x (mirror/duplicate). See [#536](https://github.com/faisalman/ua-parser-js/issues/536) for the reason behind this confusion.\n\n## Version 0.8\n\nVersion 0.8 was created by accident. This version is now deprecated and no longer maintained, please update to version 0.7 / 1.0.\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# UAParser.js Code of Conduct\n\n## Introduction\n\nWelcome to the UAParser.js community! We're here to collaborate on developing an awesome project. Here are some general guidelines to make our community a great place:\n\n### 1. Be Kind, Honest, and Respectful\n\nAlways treat others with kindness and respect. We value different opinions and encourage positive communication.\n\n### 2. Keep Conversations Civil and On-Topic\n\nPlease keep discussions related to the project. If you want to talk about something else, find the right place for it.\n\n### 3. Mutual Assistance, Appreciation, and Acknowledgement\n\nFeel free to ask for help, show gratitude for contributions, and make sure to give credit where it's due.\n\n### 4. Resolving Disagreements\n\nIn the event of a disagreement, we encourage open and respectful dialogue. It's important to remember that it's okay to have differing opinions, and if a common ground can't be reached, we suggest using the 'agree to disagree' approach.\n\n## Reporting Issues\n\nIf you see any behavior that goes against this code of conduct, report it to [f@faisalman.com](mailto:f@faisalman.com).\n\n## Conclusion\n\nTogether, we can make this project awesome!"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# UAParser.js: How to Contribute\n\n* Fork and clone this repository\n* Make some changes as required\n* Write unit test to showcase its functionality under `/test`\n* Run the test suites to make sure it's not breaking anything `$ npm run build+test`\n* Submit a pull request & check the CLA in the submission form"
  },
  {
    "path": "LICENSE.md",
    "content": "# GNU AFFERO GENERAL PUBLIC LICENSE\n\nVersion 3, 19 November 2007\n\nCopyright (C) 2007 Free Software Foundation, Inc.\n<https://fsf.org/>\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\n## Preamble\n\nThe GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\nThe licenses for most software and other practical works are designed\nto take away your freedom to share and change the works. By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains\nfree software for all its users.\n\nWhen we speak of free software, we are referring to freedom, not\nprice. Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\nDevelopers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\nA secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate. Many developers of free software are heartened and\nencouraged by the resulting cooperation. However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\nThe GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community. It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server. Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\nAn older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals. This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing\nunder this license.\n\nThe precise terms and conditions for copying, distribution and\nmodification follow.\n\n## TERMS AND CONDITIONS\n\n### 0. Definitions.\n\n\"This License\" refers to version 3 of the GNU Affero General Public\nLicense.\n\n\"Copyright\" also means copyright-like laws that apply to other kinds\nof works, such as semiconductor masks.\n\n\"The Program\" refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as \"you\". \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\nTo \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of\nan exact copy. The resulting work is called a \"modified version\" of\nthe earlier work or a work \"based on\" the earlier work.\n\nA \"covered work\" means either the unmodified Program or a work based\non the Program.\n\nTo \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy. Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\nTo \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user\nthrough a computer network, with no transfer of a copy, is not\nconveying.\n\nAn interactive user interface displays \"Appropriate Legal Notices\" to\nthe extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License. If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n### 1. Source Code.\n\nThe \"source code\" for a work means the preferred form of the work for\nmaking modifications to it. \"Object code\" means any non-source form of\na work.\n\nA \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\nThe \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form. A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\nThe \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities. However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can\nregenerate automatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same\nwork.\n\n### 2. Basic Permissions.\n\nAll rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met. This License explicitly affirms your unlimited\npermission to run the unmodified Program. The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work. This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey,\nwithout conditions so long as your license otherwise remains in force.\nYou may convey covered works to others for the sole purpose of having\nthem make modifications exclusively for you, or provide you with\nfacilities for running those works, provided that you comply with the\nterms of this License in conveying all material for which you do not\ncontrol copyright. Those thus making or running the covered works for\nyou must do so exclusively on your behalf, under your direction and\ncontrol, on terms that prohibit them from making any copies of your\ncopyrighted material outside their relationship with you.\n\nConveying under any other circumstances is permitted solely under the\nconditions stated below. Sublicensing is not allowed; section 10 makes\nit unnecessary.\n\n### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\nNo covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\nWhen you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such\ncircumvention is effected by exercising rights under this License with\nrespect to the covered work, and you disclaim any intention to limit\noperation or modification of the work as a means of enforcing, against\nthe work's users, your or third parties' legal rights to forbid\ncircumvention of technological measures.\n\n### 4. Conveying Verbatim Copies.\n\nYou may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\nYou may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n### 5. Conveying Modified Source Versions.\n\nYou may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these\nconditions:\n\n-   a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n-   b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under\n    section 7. This requirement modifies the requirement in section 4\n    to \"keep intact all notices\".\n-   c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy. This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged. This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n-   d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\nA compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n### 6. Conveying Non-Source Forms.\n\nYou may convey a covered work in object code form under the terms of\nsections 4 and 5, provided that you also convey the machine-readable\nCorresponding Source under the terms of this License, in one of these\nways:\n\n-   a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n-   b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the Corresponding\n    Source from a network server at no charge.\n-   c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source. This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n-   d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge. You need not require recipients to copy the\n    Corresponding Source along with the object code. If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source. Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n-   e) Convey the object code using peer-to-peer transmission,\n    provided you inform other peers where the object code and\n    Corresponding Source of the work are being offered to the general\n    public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\nA \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal,\nfamily, or household purposes, or (2) anything designed or sold for\nincorporation into a dwelling. In determining whether a product is a\nconsumer product, doubtful cases shall be resolved in favor of\ncoverage. For a particular product received by a particular user,\n\"normally used\" refers to a typical or common use of that class of\nproduct, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected\nto use, the product. A product is a consumer product regardless of\nwhether the product has substantial commercial, industrial or\nnon-consumer uses, unless such uses represent the only significant\nmode of use of the product.\n\n\"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to\ninstall and execute modified versions of a covered work in that User\nProduct from a modified version of its Corresponding Source. The\ninformation must suffice to ensure that the continued functioning of\nthe modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information. But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\nThe requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or\nupdates for a work that has been modified or installed by the\nrecipient, or for the User Product in which it has been modified or\ninstalled. Access to a network may be denied when the modification\nitself materially and adversely affects the operation of the network\nor violates the rules and protocols for communication across the\nnetwork.\n\nCorresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n### 7. Additional Terms.\n\n\"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law. If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit. (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.) You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders\nof that material) supplement the terms of this License with terms:\n\n-   a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n-   b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n-   c) Prohibiting misrepresentation of the origin of that material,\n    or requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n-   d) Limiting the use for publicity purposes of names of licensors\n    or authors of the material; or\n-   e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n-   f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions\n    of it) with contractual assumptions of liability to the recipient,\n    for any liability that these contractual assumptions directly\n    impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10. If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term. If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions; the\nabove requirements apply either way.\n\n### 8. Termination.\n\nYou may not propagate or modify a covered work except as expressly\nprovided under this License. Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\nHowever, if you cease all violation of this License, then your license\nfrom a particular copyright holder is reinstated (a) provisionally,\nunless and until the copyright holder explicitly and finally\nterminates your license, and (b) permanently, if the copyright holder\nfails to notify you of the violation by some reasonable means prior to\n60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License. If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n### 9. Acceptance Not Required for Having Copies.\n\nYou are not required to accept this License in order to receive or run\na copy of the Program. Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance. However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work. These actions infringe copyright if you do\nnot accept this License. Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n### 10. Automatic Licensing of Downstream Recipients.\n\nEach time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License. You are not responsible\nfor enforcing compliance by third parties with this License.\n\nAn \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations. If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License. For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n### 11. Patents.\n\nA \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The\nwork thus licensed is called the contributor's \"contributor version\".\n\nA contributor's \"essential patent claims\" are all patent claims owned\nor controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version. For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\nIn the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement). To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients. \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\nA patent license is \"discriminatory\" if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on\nthe non-exercise of one or more of the rights that are specifically\ngranted under this License. You may not convey a covered work if you\nare a party to an arrangement with a third party that is in the\nbusiness of distributing software, under which you make payment to the\nthird party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties\nwho would receive the covered work from you, a discriminatory patent\nlicense (a) in connection with copies of the covered work conveyed by\nyou (or copies made from those copies), or (b) primarily for and in\nconnection with specific products or compilations that contain the\ncovered work, unless you entered into that arrangement, or that patent\nlicense was granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n### 12. No Surrender of Others' Freedom.\n\nIf conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License. If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under\nthis License and any other pertinent obligations, then as a\nconsequence you may not convey it at all. For example, if you agree to\nterms that obligate you to collect a royalty for further conveying\nfrom those to whom you convey the Program, the only way you could\nsatisfy both those terms and this License would be to refrain entirely\nfrom conveying the Program.\n\n### 13. Remote Network Interaction; Use with the GNU General Public License.\n\nNotwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your\nversion supports such interaction) an opportunity to receive the\nCorresponding Source of your version by providing access to the\nCorresponding Source from a network server at no charge, through some\nstandard or customary means of facilitating copying of software. This\nCorresponding Source shall include the Corresponding Source for any\nwork covered by version 3 of the GNU General Public License that is\nincorporated pursuant to the following paragraph.\n\nNotwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work. The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n### 14. Revised Versions of this License.\n\nThe Free Software Foundation may publish revised and/or new versions\nof the GNU Affero General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program\nspecifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation. If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever\npublished by the Free Software Foundation.\n\nIf the Program specifies that a proxy can decide which future versions\nof the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\nLater license versions may give you additional or different\npermissions. However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n### 15. Disclaimer of Warranty.\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT\nWARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND\nPERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR\nCORRECTION.\n\n### 16. Limitation of Liability.\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR\nCONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES\nARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT\nNOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR\nLOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM\nTO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER\nPARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n### 17. Interpretation of Sections 15 and 16.\n\nIf the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\nEND OF TERMS AND CONDITIONS"
  },
  {
    "path": "README.md",
    "content": "#### Featured Sponsors\n\n[![https://ref.wisprflow.ai/Rxj3n8H](https://github.com/user-attachments/assets/e39fc98d-5d1b-4f7b-a355-4648e1f79a94)](https://ref.wisprflow.ai/Rxj3n8H)\n\n---\n\n[![https://uaparser.dev](https://raw.githubusercontent.com/faisalman/ua-parser-js/gh-pages/images/uap-header.png)](https://uaparser.dev)\n[![https://uaparser.dev](https://github.com/user-attachments/assets/a626166c-17cc-45e3-8ff6-d7e948a5ded0)](https://uaparser.dev)\n[![https://uaparser.dev](https://github.com/user-attachments/assets/50da50fc-7c8a-46e3-a2bc-6a8249914372)](https://uaparser.dev)\n[![https://uaparser.dev](https://github.com/user-attachments/assets/9f2aaff0-a9b4-4ac9-bdf3-eea8081a2582)](https://uaparser.dev)\n    \n<p align=\"center\">\n<a href=\"https://www.npmjs.com/package/ua-parser-js\"><img src=\"https://img.shields.io/npm/dw/ua-parser-js?color=red&logo=npm&label=NPM%20DOWNLOADS&style=for-the-badge\"></a>\n<a href=\"https://www.jsdelivr.com/package/npm/ua-parser-js\"><img src=\"https://img.shields.io/jsdelivr/gh/hw/faisalman/ua-parser-js?logo=jsdelivr&style=for-the-badge\"></a>\n<a href=\"https://github.com/faisalman/ua-parser-js\"><img src=\"https://img.shields.io/github/stars/faisalman/ua-parser-js?color=yellow&logo=github&style=for-the-badge\"></a>\n<a href=\"https://bundlephobia.com/package/ua-parser-js@1.0.35\"><img src=\"https://img.shields.io/bundlephobia/minzip/ua-parser-js?logo=hackthebox&logoColor=white&style=for-the-badge\"/></a>\n<a href=\"https://github.com/faisalman/ua-parser-js/graphs/contributors\"><img src=\"https://img.shields.io/github/contributors/faisalman/ua-parser-js?color=purple&logo=githubsponsors&style=for-the-badge\"></a>\n<a href=\"https://www.npmjs.com/package/ua-parser-js\"><img src=\"https://img.shields.io/npm/v/ua-parser-js.svg?logo=npm&color=red&style=for-the-badge\"></a>\n<a href=\"https://cdnjs.com/libraries/UAParser.js\"><img src=\"https://img.shields.io/cdnjs/v/UAParser.js.svg?color=orange&style=for-the-badge\"></a>\n<img src=\"https://img.shields.io/ossf-scorecard/github.com/faisalman/ua-parser-js?label=openssf%20scorecard&style=for-the-badge\">\n<a target=\"_blank\" href=\"https://discord.com/channels/1406959509087453236/1406959509930381375\"><img alt=\"Discord invite\" src=\"https://dcbadge.limes.pink/api/server/https://discord.com/channels/1406959509087453236/1406959509930381375\"></a>\n</p>\n\n# UAParser.js\n\nThe most comprehensive, compact, and up-to-date JavaScript library to detect user's browser, OS, CPU, and device type/model. Also detect bots, apps, and more. Runs seamlessly in the browser (client-side) or Node.js (server-side).\n\n# Demo\n\n  * Live demo: https://uaparser.dev\n\n\n# Documentation\n\n  * `version 1.x` : https://github.com/faisalman/ua-parser-js/tree/1.0.x#documentation\n  * `version 2.x` : https://docs.uaparser.dev\n\nBefore upgrading from `v0.7` / `v1.0`, please read [CHANGELOG](CHANGELOG.md) to \nsee what's new & breaking.\n\n# Package & Pricing\n\n<table>\n    <thead>\n        <tr>\n            <th></th>\n            <th colspan=\"2\">Open-Source Editions</th>\n            <th colspan=\"3\">PRO / Commercial Editions</th>\n        </tr>\n    </thead>\n    <tbody>\n        <tr>\n            <td>License options</td>\n            <td>MIT (v1.x)</td>\n            <td>AGPL (v2.x)</td>\n            <td>PRO Personal</td>\n            <td>PRO Business</td>\n            <td>PRO Enterprise</td>\n        </tr>\n        <tr>\n            <td>Browser Detection</td>\n            <td><a href=\"#demo\" title=\"Basic detection\">⚠️</a></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>CPU Detection</td>\n            <td><a href=\"#demo\" title=\"Basic detection\">⚠️</a></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Device Detection</td>\n            <td><a href=\"#demo\" title=\"Basic detection\">⚠️</a></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Rendering Engine Detection</td>\n            <td><a href=\"#demo\" title=\"Basic detection\">⚠️</a></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>OS detection</td>\n            <td><a href=\"#demo\" title=\"Basic detection\">⚠️</a></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Enhanced+ Accuracy</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Bot Detection</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>AI Detection</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Extra Detections (Apps, Libs, Emails, Media Players, Crawlers, and more)</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Client Hints Support</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>CommonJS Support</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>ESM Support</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>TypeScript Definitions</td>\n            <td><a href=\"#demo\" title=\"Community version\">✅</a></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>npm Module Available</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Direct Downloads Available</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Commercial Use Allowed</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Permissive (non-Copyleft) License</td>\n            <td>✅</td>\n            <td><strong title=\"Copyleft license\">❌</strong></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>No Open-Source Obligations</td>\n            <td>✅</td>\n            <td><strong title=\"Copyleft license\">❌</strong></td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Unlimited End-Products</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td><strong title=\"1 end-product per license\">❌</strong></td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Unlimited Deployments</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td><strong title=\"1 TLD or deliverable per license\">❌</strong></td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>1-year Product Support</td>\n            <td>❌</td>\n            <td>❌</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Lifetime Updates</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n            <td>✅</td>\n        </tr>\n        <tr>\n            <td>Price</td>\n            <td><strong title=\"Pay as you want\">FREE<sup>*</sup> (<a target=\"_blank\" href=\"https://raw.githubusercontent.com/faisalman/ua-parser-js/1.0.x/license.md\">License</a>)</strong></td>\n            <td><strong title=\"Pay as you want\">FREE<sup>*</sup> (<a target=\"_blank\" href=\"https://raw.githubusercontent.com/faisalman/ua-parser-js/master/LICENSE.md\">License</a>)</strong></td>\n            <td><strong title=\"$14 (one-time fee)\">$14 (<a target=\"_blank\" href=\"https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-personal/LICENSE.md\">License</a>)</strong></td>\n            <td><strong title=\"$29 (one-time fee)\">$29 (<a target=\"_blank\" href=\"https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-business/LICENSE.md\">License</a>)</strong></td>\n            <td><strong title=\"$599 (one-time fee)\">$599 (<a target=\"_blank\" href=\"https://raw.githubusercontent.com/faisalman/ua-parser-js/pro-enterprise/LICENSE.md\">License</a>)</strong></td>\n        </tr>\n    </tbody>\n    <tfoot>\n        <tr>\n            <th align=\"right\" colspan=\"6\">\n                <h3><a target=\"_blank\" href=\"https://uaparserjs.lemonsqueezy.com/buy/e236ea87-9b2b-400e-9683-24367f731b35\"> GET THE PRO PACKAGES 📥</a></h3>\n            </th>\n        </tr>\n    </tfoot>\n</table>\n\n# Development\n\n## Contributors\n\nPlease read [CONTRIBUTING](CONTRIBUTING.md) guide first for the instruction details.\n\n<a href=\"https://github.com/faisalman/ua-parser-js/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?repo=faisalman/ua-parser-js\" />\n</a>\n\nMade with [contributors-img](https://contrib.rocks).\n\n## Backers & Sponsors\n\nSupport the **open-source editions** of UAParser.js through one of the following options:\n\n[![OpenCollective](https://img.shields.io/badge/OpenCollective-dddddd?style=for-the-badge&logo=opencollective&color=dddddd\n)](https://opencollective.com/ua-parser-js)\n[![GitHub Sponsors](https://img.shields.io/badge/GitHub_Sponsors-333333?style=for-the-badge&logo=githubsponsors&color=333333\n)](https://github.com/sponsors/faisalman)\n[![PayPal](https://img.shields.io/badge/Paypal-003087?style=for-the-badge&logo=paypal&color=003087\n)](https://paypal.me/faisalman)\n[![WeChat/Alipay](https://img.shields.io/badge/Other_Payment_Methods-Alipay_/_WeChat_Pay-09b83e?style=for-the-badge&logo=mastercard&color=09b83e\n)](https://uaparserjs.lemonsqueezy.com/checkout/buy/3d71f2f3-cf4d-473c-892a-9d4497c890be)\n\n<a href=\"https://opencollective.com/ua-parser-js\"><img src=\"https://opencollective.com/ua-parser-js/organizations.svg?avatarHeight=64\"></a>\n<a href=\"https://opencollective.com/ua-parser-js\"><img src=\"https://opencollective.com/ua-parser-js/individuals.svg?avatarHeight=64\"></a>\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Reporting a Vulnerability\n\nTo report a security issue, please email `f@faisalman.com` with a description of the issue, reproducible steps to get the issue, affected versions, and, if known, mitigations for the issue.\n\nIf the issue is confirmed as a vulnerability, we will open a new security advisory draft in our GitHub's Security Advisory page [https://github.com/faisalman/ua-parser-js/security/advisories](https://github.com/faisalman/ua-parser-js/security/advisories) and acknowledge your contributions as part of it. This project follows a 90 days disclosure timeline."
  },
  {
    "path": "dist/icons/color/LICENSE.md",
    "content": "MIT License\nCopyright (c) Cătălin Mariș\nhttps://github.com/alrra/browser-logos"
  },
  {
    "path": "dist/icons/mono/LICENSE.md",
    "content": "CC0-1.0\nhttps://github.com/simple-icons/simple-icons\nhttps://github.com/coreui/coreui-icons"
  },
  {
    "path": "dist/ua-parser.html",
    "content": "<script src=\"./ua-parser.min.js\"></script>\n"
  },
  {
    "path": "dist/ua-parser.min.mjs",
    "content": "/* UAParser.js v2.0.9\n   Copyright © 2012-2026 Faisal Salman <f@faisalman.com>\n   AGPLv3 License */\nvar LIBVERSION=\"2.0.9\",UA_MAX_LENGTH=500,USER_AGENT=\"user-agent\",EMPTY=\"\",UNKNOWN=\"?\",TYPEOF={FUNCTION:\"function\",OBJECT:\"object\",STRING:\"string\",UNDEFINED:\"undefined\"},BROWSER=\"browser\",CPU=\"cpu\",DEVICE=\"device\",ENGINE=\"engine\",OS=\"os\",RESULT=\"result\",NAME=\"name\",TYPE=\"type\",VENDOR=\"vendor\",VERSION=\"version\",ARCHITECTURE=\"architecture\",MAJOR=\"major\",MODEL=\"model\",CONSOLE=\"console\",MOBILE=\"mobile\",TABLET=\"tablet\",SMARTTV=\"smarttv\",WEARABLE=\"wearable\",XR=\"xr\",EMBEDDED=\"embedded\",FETCHER=\"fetcher\",INAPP=\"inapp\",BRANDS=\"brands\",FORMFACTORS=\"formFactors\",FULLVERLIST=\"fullVersionList\",PLATFORM=\"platform\",PLATFORMVER=\"platformVersion\",BITNESS=\"bitness\",CH=\"sec-ch-ua\",CH_FULL_VER_LIST=CH+\"-full-version-list\",CH_ARCH=CH+\"-arch\",CH_BITNESS=CH+\"-\"+BITNESS,CH_FORM_FACTORS=CH+\"-form-factors\",CH_MOBILE=CH+\"-\"+MOBILE,CH_MODEL=CH+\"-\"+MODEL,CH_PLATFORM=CH+\"-\"+PLATFORM,CH_PLATFORM_VER=CH_PLATFORM+\"-version\",CH_ALL_VALUES=[BRANDS,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON=\"Amazon\",APPLE=\"Apple\",ASUS=\"ASUS\",BLACKBERRY=\"BlackBerry\",GOOGLE=\"Google\",HUAWEI=\"Huawei\",LENOVO=\"Lenovo\",HONOR=\"Honor\",LG=\"LG\",MICROSOFT=\"Microsoft\",MOTOROLA=\"Motorola\",NVIDIA=\"Nvidia\",ONEPLUS=\"OnePlus\",OPPO=\"OPPO\",SAMSUNG=\"Samsung\",SHARP=\"Sharp\",SONY=\"Sony\",XIAOMI=\"Xiaomi\",ZEBRA=\"Zebra\",CHROME=\"Chrome\",CHROMIUM=\"Chromium\",CHROMECAST=\"Chromecast\",EDGE=\"Edge\",FIREFOX=\"Firefox\",OPERA=\"Opera\",FACEBOOK=\"Facebook\",SOGOU=\"Sogou\",PREFIX_MOBILE=\"Mobile \",SUFFIX_BROWSER=\" Browser\",WINDOWS=\"Windows\";var isWindow=typeof window!==TYPEOF.UNDEFINED,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i<arr.length;i++){enums[arr[i].toUpperCase()]=arr[i]}return enums},has=function(str1,str2){if(typeof str1===TYPEOF.OBJECT&&str1.length>0){for(var i in str1){if(lowerize(str2)==lowerize(str1[i]))return true}return false}return isString(str1)?lowerize(str2)==lowerize(str1):false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===TYPEOF.STRING},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=strip(/\\\\?\\\"/g,header).split(\",\");for(var i=0;i<tokens.length;i++){if(tokens[i].indexOf(\";\")>-1){var token=trim(tokens[i]).split(\";v=\");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\\d\\.]/g,version).split(\".\")[0]:undefined},setProps=function(arr){for(var i in arr){if(!arr.hasOwnProperty(i))continue;var propName=arr[i];if(typeof propName==TYPEOF.OBJECT&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},stripQuotes=function(str){return strip(/\\\\?\\\"/g,str)},trim=function(str,len){str=strip(/^\\s\\s*/,String(str));return typeof len===TYPEOF.UNDEFINED?str:str.substring(0,len)};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i<arrays.length&&!matches){var regex=arrays[i],props=arrays[i+1];j=k=0;while(j<regex.length&&!matches){if(!regex[j]){break}matches=regex[j++].exec(ua);if(!!matches){for(p=0;p<props.length;p++){match=matches[++k];q=props[p];if(typeof q===TYPEOF.OBJECT&&q.length>0){if(q.length===2){if(typeof q[1]==TYPEOF.FUNCTION){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length>=3){if(typeof q[1]===TYPEOF.FUNCTION&&!(q[1].exec&&q[1].test)){if(q.length>3){this[q[0]]=match?q[1].apply(this,q.slice(2)):undefined}else{this[q[0]]=match?q[1].call(this,match,q[2]):undefined}}else{if(q.length==3){this[q[0]]=match?match.replace(q[1],q[2]):undefined}else if(q.length==4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}else if(q.length>4){this[q[0]]=match?q[3].apply(this,[match.replace(q[1],q[2])].concat(q.slice(4))):undefined}}}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===TYPEOF.OBJECT&&map[i].length>0){for(var j=0;j<map[i].length;j++){if(has(map[i][j],str)){return i===UNKNOWN?undefined:i}}}else if(has(map[i],str)){return i===UNKNOWN?undefined:i}}return map.hasOwnProperty(\"*\")?map[\"*\"]:str};var windowsVersionMap={ME:\"4.90\",\"NT 3.51\":\"3.51\",\"NT 4.0\":\"4.0\",2e3:[\"5.0\",\"5.01\"],XP:[\"5.1\",\"5.2\"],Vista:\"6.0\",7:\"6.1\",8:\"6.2\",8.1:\"6.3\",10:[\"6.4\",\"10.0\"],NT:\"\"},formFactorsMap={embedded:\"Automotive\",mobile:\"Mobile\",tablet:[\"Tablet\",\"EInk\"],smarttv:\"TV\",wearable:\"Watch\",xr:[\"VR\",\"XR\"],\"?\":[\"Desktop\",\"Unknown\"],\"*\":undefined},browserHintsMap={Chrome:\"Google Chrome\",Edge:\"Microsoft Edge\",\"Edge WebView2\":\"Microsoft Edge WebView2\",\"Chrome WebView\":\"Android WebView\",\"Chrome Headless\":\"HeadlessChrome\",\"Huawei Browser\":\"HuaweiBrowser\",\"MIUI Browser\":\"Miui Browser\",\"Opera Mobi\":\"OperaMobile\",Yandex:\"YaBrowser\"};var defaultRegexes={browser:[[/\\b(?:crmo|crios)\\/([\\w\\.]+)/i],[VERSION,[NAME,PREFIX_MOBILE+\"Chrome\"]],[/webview.+edge\\/([\\w\\.]+)/i],[VERSION,[NAME,EDGE+\" WebView\"]],[/edg(?:e|ios|a)?\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Edge\"]],[/(opera mini)\\/([-\\w\\.]+)/i,/(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i,/(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i],[NAME,VERSION],[/opios[\\/ ]+([\\w\\.]+)/i],[VERSION,[NAME,OPERA+\" Mini\"]],[/\\bop(?:rg)?x\\/([\\w\\.]+)/i],[VERSION,[NAME,OPERA+\" GX\"]],[/\\bopr\\/([\\w\\.]+)/i],[VERSION,[NAME,OPERA]],[/\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i],[VERSION,[NAME,\"Baidu\"]],[/\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i],[VERSION,[NAME,\"Maxthon\"]],[/(kindle)\\/([\\w\\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i,/(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i,/(?:ms|\\()(ie) ([\\w\\.]+)/i,/(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\\/v?([-\\w\\.]+)/i,/(brave)(?: chrome)?\\/([\\d\\.]+)/i,/(aloha|heytap|ovi|115|surf|qwant)browser\\/([\\d\\.]+)/i,/(qwant)(?:ios|mobile)\\/([\\d\\.]+)/i,/(ecosia|weibo)(?:__| \\w+@)([\\d\\.]+)/i],[NAME,VERSION],[/quark(?:pc)?\\/([-\\w\\.]+)/i],[VERSION,[NAME,\"Quark\"]],[/\\bddg\\/([\\w\\.]+)/i],[VERSION,[NAME,\"DuckDuckGo\"]],[/(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i],[VERSION,[NAME,\"UCBrowser\"]],[/microm.+\\bqbcore\\/([\\w\\.]+)/i,/\\bqbcore\\/([\\w\\.]+).+microm/i,/micromessenger\\/([\\w\\.]+)/i],[VERSION,[NAME,\"WeChat\"]],[/konqueror\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Konqueror\"]],[/trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i],[VERSION,[NAME,\"IE\"]],[/ya(?:search)?browser\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Yandex\"]],[/slbrowser\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Smart \"+LENOVO+SUFFIX_BROWSER]],[/(av(?:ast|g|ira))\\/([\\w\\.]+)/i],[[NAME,/(.+)/,\"$1 Secure\"+SUFFIX_BROWSER],VERSION],[/norton\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Norton Private\"+SUFFIX_BROWSER]],[/\\bfocus\\/([\\w\\.]+)/i],[VERSION,[NAME,FIREFOX+\" Focus\"]],[/ mms\\/([\\w\\.]+)$/i],[VERSION,[NAME,OPERA+\" Neon\"]],[/ opt\\/([\\w\\.]+)$/i],[VERSION,[NAME,OPERA+\" Touch\"]],[/coc_coc\\w+\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Coc Coc\"]],[/dolfin\\/([\\w\\.]+)/i],[VERSION,[NAME,\"Dolphin\"]],[/coast\\/([\\w\\.]+)/i],[VERSION,[NAME,OPERA+\" Coast\"]],[/miuibrowser\\/([\\w\\.]+)/i],[VERSION,[NAME,\"MIUI\"+SUFFIX_BROWSER]],[/fxios\\/([\\w\\.-]+)/i],[VERSION,[NAME,PREFIX_MOBILE+FIREFOX]],[/\\bqihoobrowser\\/?([\\w\\.]*)/i],[VERSION,[NAME,\"360\"]],[/\\b(qq)\\/([\\w\\.]+)/i],[[NAME,/(.+)/,\"$1Browser\"],VERSION],[/(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i],[[NAME,/(.+)/,\"$1\"+SUFFIX_BROWSER],VERSION],[/samsungbrowser\\/([\\w\\.]+)/i],[VERSION,[NAME,SAMSUNG+\" Internet\"]],[/metasr[\\/ ]?([\\d\\.]+)/i],[VERSION,[NAME,SOGOU+\" Explorer\"]],[/(sogou)mo\\w+\\/([\\d\\.]+)/i],[[NAME,SOGOU+\" Mobile\"],VERSION],[/(electron)\\/([\\w\\.]+) safari/i,/(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i,/m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i],[NAME,VERSION],[/(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i],[NAME],[/ome\\/([\\w\\.]+).+(iron(?= saf)|360(?=[es]e$))/i],[VERSION,NAME],[/((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i],[[NAME,FACEBOOK],VERSION,[TYPE,INAPP]],[/(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i,/(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i,/(daum)apps[\\/ ]([\\w\\.]+)/i,/safari (line)\\/([\\w\\.]+)/i,/\\b(line)\\/([\\w\\.]+)\\/iab/i,/(alipay)client\\/([\\w\\.]+)/i,/(twitter)(?:and| f.+e\\/([\\w\\.]+))/i,/(bing)(?:web|sapphire)\\/([\\w\\.]+)/i,/(instagram|snapchat|klarna)[\\/ ]([-\\w\\.]+)/i],[NAME,VERSION,[TYPE,INAPP]],[/\\bgsa\\/([\\w\\.]+) .*safari\\//i],[VERSION,[NAME,\"GSA\"],[TYPE,INAPP]],[/(?:musical_ly|trill)(?:.+app_?version\\/|_)([\\w\\.]+)/i],[VERSION,[NAME,\"TikTok\"],[TYPE,INAPP]],[/\\[(linkedin)app\\]/i],[NAME,[TYPE,INAPP]],[/(zalo(?:app)?)[\\/\\sa-z]*([\\w\\.-]+)/i],[[NAME,/(.+)/,\"Zalo\"],VERSION,[TYPE,INAPP]],[/(chromium)[\\/ ]([-\\w\\.]+)/i],[NAME,VERSION],[/ome-(lighthouse)$/i],[NAME,[TYPE,FETCHER]],[/headlesschrome(?:\\/([\\w\\.]+)| )/i],[VERSION,[NAME,CHROME+\" Headless\"]],[/wv\\).+chrome\\/([\\w\\.]+).+edgw\\//i],[VERSION,[NAME,EDGE+\" WebView2\"]],[/ wv\\).+(chrome)\\/([\\w\\.]+)/i],[[NAME,CHROME+\" WebView\"],VERSION],[/droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i],[VERSION,[NAME,\"Android\"+SUFFIX_BROWSER]],[/chrome\\/([\\w\\.]+) mobile/i],[VERSION,[NAME,PREFIX_MOBILE+\"Chrome\"]],[/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i],[NAME,VERSION],[/version\\/([\\w\\.\\,]+) .*mobile(?:\\/\\w+ | ?)safari/i],[VERSION,[NAME,PREFIX_MOBILE+\"Safari\"]],[/iphone .*mobile(?:\\/\\w+ | ?)safari/i],[[NAME,PREFIX_MOBILE+\"Safari\"]],[/version\\/([\\w\\.\\,]+) .*(safari)/i],[VERSION,NAME],[/webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i],[NAME,[VERSION,\"1\"]],[/(webkit|khtml)\\/([\\w\\.]+)/i],[NAME,VERSION],[/(?:mobile|tablet);.*(firefox)\\/([\\w\\.-]+)/i],[[NAME,PREFIX_MOBILE+FIREFOX],VERSION],[/(navigator|netscape\\d?)\\/([-\\w\\.]+)/i],[[NAME,\"Netscape\"],VERSION],[/(wolvic|librewolf)\\/([\\w\\.]+)/i],[NAME,VERSION],[/mobile vr; rv:([\\w\\.]+)\\).+firefox/i],[VERSION,[NAME,FIREFOX+\" Reality\"]],[/ekiohf.+(flow)\\/([\\w\\.]+)/i,/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\\/([-\\w\\.]+)$/i,/(firefox)\\/([\\w\\.]+)/i,/(mozilla)\\/([\\w\\.]+(?= .+rv\\:.+gecko\\/\\d+)|[0-4][\\w\\.]+(?!.+compatible))/i,/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,/\\b(links) \\(([\\w\\.]+)/i],[NAME,[VERSION,/_/g,\".\"]],[/(cobalt)\\/([\\w\\.]+)/i],[NAME,[VERSION,/[^\\d\\.]+./,EMPTY]]],cpu:[[/\\b((amd|x|x86[-_]?|wow|win)64)\\b/i],[[ARCHITECTURE,\"amd64\"]],[/(ia32(?=;))/i,/\\b((i[346]|x)86)(pc)?\\b/i],[[ARCHITECTURE,\"ia32\"]],[/\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i],[[ARCHITECTURE,\"arm64\"]],[/\\b(arm(v[67])?ht?n?[fl]p?)\\b/i],[[ARCHITECTURE,\"armhf\"]],[/( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i],[[ARCHITECTURE,\"arm\"]],[/ sun4\\w[;\\)]/i],[[ARCHITECTURE,\"sparc\"]],[/\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i,/((ppc|powerpc)(64)?)( mac|;|\\))/i,/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i],[[ARCHITECTURE,/ower/,EMPTY,lowerize]],[/mc680.0/i],[[ARCHITECTURE,\"68k\"]],[/winnt.+\\[axp/i],[[ARCHITECTURE,\"alpha\"]]],device:[[/\\b(sch-i[89]0\\d|shw-m380s|sm-[ptx]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus 10)/i],[MODEL,[VENDOR,SAMSUNG],[TYPE,TABLET]],[/\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,/samsung[- ]((?!sm-[lr]|browser)[-\\w]+)/i,/sec-(sgh\\w+)/i],[MODEL,[VENDOR,SAMSUNG],[TYPE,MOBILE]],[/(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)[\\/\\);]/i],[MODEL,[VENDOR,APPLE],[TYPE,MOBILE]],[/\\b(?:ios|apple\\w+)\\/.+[\\(\\/](ipad)/i,/\\b(ipad)[\\d,]*[;\\] ].+(mac |i(pad)?)os/i],[MODEL,[VENDOR,APPLE],[TYPE,TABLET]],[/(macintosh);/i],[MODEL,[VENDOR,APPLE]],[/\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i],[MODEL,[VENDOR,SHARP],[TYPE,MOBILE]],[/\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i],[MODEL,[VENDOR,HONOR],[TYPE,TABLET]],[/honor([-\\w ]+)[;\\)]/i],[MODEL,[VENDOR,HONOR],[TYPE,MOBILE]],[/\\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\\w\\. ]*(?= bui|\\)))\\b(?!.+d\\/s)/i],[MODEL,[VENDOR,HUAWEI],[TYPE,TABLET]],[/(?:huawei) ?([-\\w ]+)[;\\)]/i,/\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][\\dc][adnt]?)\\b(?!.+d\\/s)/i],[MODEL,[VENDOR,HUAWEI],[TYPE,MOBILE]],[/oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,/\\b(?:xiao)?((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i],[[MODEL,/_/g,\" \"],[VENDOR,XIAOMI],[TYPE,TABLET]],[/\\b; (\\w+) build\\/hm\\1/i,/\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i,/oid[^\\)]+; (redmi[\\-_ ]?(?:note|k)?[\\w_ ]+|m?[12]\\d[01]\\d\\w{3,6}|poco[\\w ]+|(shark )?\\w{3}-[ah]0|qin ?[1-3](s\\+|ultra| pro)?)( bui|; wv|\\))/i,/\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\\d{0,2}\\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\\))/i,/ ([\\w ]+) miui\\/v?\\d/i],[[MODEL,/_/g,\" \"],[VENDOR,XIAOMI],[TYPE,MOBILE]],[/droid.+; (cph2[3-6]\\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\\d|p[g-l]\\w[1m]10)\\b/i,/(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i],[MODEL,[VENDOR,ONEPLUS],[TYPE,MOBILE]],[/; (\\w+) bui.+ oppo/i,/\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i],[MODEL,[VENDOR,OPPO],[TYPE,MOBILE]],[/\\b(opd2(\\d{3}a?))(?: bui|\\))/i],[MODEL,[VENDOR,strMapper,{OnePlus:[\"203\",\"304\",\"403\",\"404\",\"413\",\"415\"],\"*\":OPPO}],[TYPE,TABLET]],[/(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\\w\\+ ]*)(?: bui|\\))/i],[MODEL,[VENDOR,\"BLU\"],[TYPE,MOBILE]],[/; vivo (\\w+)(?: bui|\\))/i,/\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i],[MODEL,[VENDOR,\"Vivo\"],[TYPE,MOBILE]],[/\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i],[MODEL,[VENDOR,\"Realme\"],[TYPE,MOBILE]],[/(ideatab[-\\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\\d{3,4}(?:f[cu]|xu|[av])|yt\\d?-[jx]?\\d+[lfmx])( bui|;|\\)|\\/)/i,/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i],[MODEL,[VENDOR,LENOVO],[TYPE,TABLET]],[/lenovo[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i],[MODEL,[VENDOR,LENOVO],[TYPE,MOBILE]],[/\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,/\\bmot(?:orola)?[- ]([\\w\\s]+)(\\)| bui)/i,/((?:moto(?! 360)[-\\w\\(\\) ]+|xt\\d{3,4}[cgkosw\\+]?[-\\d]*|nexus 6)(?= bui|\\)))/i],[MODEL,[VENDOR,MOTOROLA],[TYPE,MOBILE]],[/\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i],[MODEL,[VENDOR,MOTOROLA],[TYPE,TABLET]],[/\\b(?:lg)?([vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i],[MODEL,[VENDOR,LG],[TYPE,TABLET]],[/(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,/\\blg[-e;\\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\\w+)/i,/\\blg-?([\\d\\w]+) bui/i],[MODEL,[VENDOR,LG],[TYPE,MOBILE]],[/(nokia) (t[12][01])/i],[VENDOR,MODEL,[TYPE,TABLET]],[/(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,/nokia[-_ ]?(([-\\w\\. ]*?))( bui|\\)|;|\\/)/i],[[MODEL,/_/g,\" \"],[TYPE,MOBILE],[VENDOR,\"Nokia\"]],[/(pixel (c|tablet))\\b/i],[MODEL,[VENDOR,GOOGLE],[TYPE,TABLET]],[/droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\\d ]*a?( pro)?( xl)?( fold)?( \\(5g\\))?)( bui|\\))/i],[MODEL,[VENDOR,GOOGLE],[TYPE,MOBILE]],[/(google) (pixelbook( go)?)/i],[VENDOR,MODEL],[/droid.+; (a?\\d[0-2]{2}so|[c-g]\\d{4}|so[-gl]\\w+|xq-\\w\\w\\d\\d)(?= bui|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i],[MODEL,[VENDOR,SONY],[TYPE,MOBILE]],[/sony tablet [ps]/i,/\\b(?:sony)?sgp\\w+(?: bui|\\))/i],[[MODEL,\"Xperia Tablet\"],[VENDOR,SONY],[TYPE,TABLET]],[/(alexa)webm/i,/(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i,/(kf[a-z]+)( bui|\\)).+silk\\//i],[MODEL,[VENDOR,AMAZON],[TYPE,TABLET]],[/((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i],[[MODEL,/(.+)/g,\"Fire Phone $1\"],[VENDOR,AMAZON],[TYPE,MOBILE]],[/(playbook);[-\\w\\),; ]+(rim)/i],[MODEL,VENDOR,[TYPE,TABLET]],[/\\b((?:bb[a-f]|st[hv])100-\\d)/i,/(?:blackberry|\\(bb10;) (\\w+)/i],[MODEL,[VENDOR,BLACKBERRY],[TYPE,MOBILE]],[/(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i],[MODEL,[VENDOR,ASUS],[TYPE,TABLET]],[/ (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i],[MODEL,[VENDOR,ASUS],[TYPE,MOBILE]],[/(nexus 9)/i],[MODEL,[VENDOR,\"HTC\"],[TYPE,TABLET]],[/(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i,/(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,/(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i],[VENDOR,[MODEL,/_/g,\" \"],[TYPE,MOBILE]],[/tcl (xess p17aa)/i,/droid [\\w\\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\\w(\\w|\\w\\w))?(\\)| bui)/i],[MODEL,[VENDOR,\"TCL\"],[TYPE,TABLET]],[/droid [\\w\\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\\w(\\w|\\w\\w))?(\\)| bui)/i],[MODEL,[VENDOR,\"TCL\"],[TYPE,MOBILE]],[/(itel) ((\\w+))/i],[[VENDOR,lowerize],MODEL,[TYPE,strMapper,{tablet:[\"p10001l\",\"w7001\"],\"*\":\"mobile\"}]],[/droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i],[MODEL,[VENDOR,\"Acer\"],[TYPE,TABLET]],[/droid.+; (m[1-5] note) bui/i,/\\bmz-([-\\w]{2,})/i],[MODEL,[VENDOR,\"Meizu\"],[TYPE,MOBILE]],[/; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i],[MODEL,[VENDOR,\"Ulefone\"],[TYPE,MOBILE]],[/; (energy ?\\w+)(?: bui|\\))/i,/; energizer ([\\w ]+)(?: bui|\\))/i],[MODEL,[VENDOR,\"Energizer\"],[TYPE,MOBILE]],[/; cat (b35);/i,/; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i],[MODEL,[VENDOR,\"Cat\"],[TYPE,MOBILE]],[/((?:new )?andromax[\\w- ]+)(?: bui|\\))/i],[MODEL,[VENDOR,\"Smartfren\"],[TYPE,MOBILE]],[/droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i],[MODEL,[VENDOR,\"Nothing\"],[TYPE,MOBILE]],[/; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,/archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i],[MODEL,[VENDOR,\"Archos\"],[TYPE,TABLET]],[/archos ([\\w ]+)( b|\\))/i,/; (ac[3-6]\\d\\w{2,8})( b|\\))/i],[MODEL,[VENDOR,\"Archos\"],[TYPE,MOBILE]],[/; (n159v)/i],[MODEL,[VENDOR,\"HMD\"],[TYPE,MOBILE]],[/(imo) (tab \\w+)/i,/(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i],[VENDOR,MODEL,[TYPE,TABLET]],[/(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\\w\\+ ]+?)(?: bui|\\)|; r)/i,/(hp) ([\\w ]+\\w)/i,/(microsoft); (lumia[\\w ]+)/i,/(oppo) ?([\\w ]+) bui/i,/(hisense) ([ehv][\\w ]+)\\)/i,/droid[^;]+; (philips)[_ ]([sv-x][\\d]{3,4}[xz]?)/i],[VENDOR,MODEL,[TYPE,MOBILE]],[/(kobo)\\s(ereader|touch)/i,/(hp).+(touchpad(?!.+tablet)|tablet)/i,/(kindle)\\/([\\w\\.]+)/i],[VENDOR,MODEL,[TYPE,TABLET]],[/(surface duo)/i],[MODEL,[VENDOR,MICROSOFT],[TYPE,TABLET]],[/droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i],[MODEL,[VENDOR,\"Fairphone\"],[TYPE,MOBILE]],[/((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i],[MODEL,[VENDOR,NVIDIA],[TYPE,TABLET]],[/(sprint) (\\w+)/i],[VENDOR,MODEL,[TYPE,MOBILE]],[/(kin\\.[onetw]{3})/i],[[MODEL,/\\./g,\" \"],[VENDOR,MICROSOFT],[TYPE,MOBILE]],[/droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i],[MODEL,[VENDOR,ZEBRA],[TYPE,TABLET]],[/droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i],[MODEL,[VENDOR,ZEBRA],[TYPE,MOBILE]],[/(philips)[\\w ]+tv/i,/smart-tv.+(samsung)/i],[VENDOR,[TYPE,SMARTTV]],[/hbbtv.+maple;(\\d+)/i],[[MODEL,/^/,\"SmartTV\"],[VENDOR,SAMSUNG],[TYPE,SMARTTV]],[/(vizio)(?: |.+model\\/)(\\w+-\\w+)/i,/tcast.+(lg)e?. ([-\\w]+)/i],[VENDOR,MODEL,[TYPE,SMARTTV]],[/(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i],[[VENDOR,LG],[TYPE,SMARTTV]],[/(apple) ?tv/i],[VENDOR,[MODEL,APPLE+\" TV\"],[TYPE,SMARTTV]],[/crkey.*devicetype\\/chromecast/i],[[MODEL,CHROMECAST+\" Third Generation\"],[VENDOR,GOOGLE],[TYPE,SMARTTV]],[/crkey.*devicetype\\/([^/]*)/i],[[MODEL,/^/,\"Chromecast \"],[VENDOR,GOOGLE],[TYPE,SMARTTV]],[/fuchsia.*crkey/i],[[MODEL,CHROMECAST+\" Nest Hub\"],[VENDOR,GOOGLE],[TYPE,SMARTTV]],[/crkey/i],[[MODEL,CHROMECAST],[VENDOR,GOOGLE],[TYPE,SMARTTV]],[/(portaltv)/i],[MODEL,[VENDOR,FACEBOOK],[TYPE,SMARTTV]],[/droid.+aft(\\w+)( bui|\\))/i],[MODEL,[VENDOR,AMAZON],[TYPE,SMARTTV]],[/(shield \\w+ tv)/i],[MODEL,[VENDOR,NVIDIA],[TYPE,SMARTTV]],[/\\(dtv[\\);].+(aquos)/i,/(aquos-tv[\\w ]+)\\)/i],[MODEL,[VENDOR,SHARP],[TYPE,SMARTTV]],[/(bravia[\\w ]+)( bui|\\))/i],[MODEL,[VENDOR,SONY],[TYPE,SMARTTV]],[/(mi(tv|box)-?\\w+) bui/i],[MODEL,[VENDOR,XIAOMI],[TYPE,SMARTTV]],[/Hbbtv.*(technisat) (.*);/i],[VENDOR,MODEL,[TYPE,SMARTTV]],[/\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i,/hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i],[[VENDOR,/.+\\/(\\w+)/,\"$1\",strMapper,{LG:\"lge\"}],[MODEL,trim],[TYPE,SMARTTV]],[/(playstation \\w+)/i],[MODEL,[VENDOR,SONY],[TYPE,CONSOLE]],[/\\b(xbox(?: one)?(?!; xbox))[\\); ]/i],[MODEL,[VENDOR,MICROSOFT],[TYPE,CONSOLE]],[/(ouya)/i,/(nintendo) (\\w+)/i,/(retroid) (pocket ([^\\)]+))/i,/(valve).+(steam deck)/i,/droid.+; ((shield|rgcube|gr0006))( bui|\\))/i],[[VENDOR,strMapper,{Nvidia:\"Shield\",Anbernic:\"RGCUBE\",Logitech:\"GR0006\"}],MODEL,[TYPE,CONSOLE]],[/\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i],[MODEL,[VENDOR,SAMSUNG],[TYPE,WEARABLE]],[/((pebble))app/i,/(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i],[VENDOR,MODEL,[TYPE,WEARABLE]],[/(ow(?:19|20)?we?[1-3]{1,3})/i],[MODEL,[VENDOR,OPPO],[TYPE,WEARABLE]],[/(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i],[MODEL,[VENDOR,APPLE],[TYPE,WEARABLE]],[/(opwwe\\d{3})/i],[MODEL,[VENDOR,ONEPLUS],[TYPE,WEARABLE]],[/(moto 360)/i],[MODEL,[VENDOR,MOTOROLA],[TYPE,WEARABLE]],[/(smartwatch 3)/i],[MODEL,[VENDOR,SONY],[TYPE,WEARABLE]],[/(g watch r)/i],[MODEL,[VENDOR,LG],[TYPE,WEARABLE]],[/droid.+; (wt63?0{2,3})\\)/i],[MODEL,[VENDOR,ZEBRA],[TYPE,WEARABLE]],[/droid.+; (glass) \\d/i],[MODEL,[VENDOR,GOOGLE],[TYPE,XR]],[/(pico) ([\\w ]+) os\\d/i],[VENDOR,MODEL,[TYPE,XR]],[/(quest( \\d| pro)?s?).+vr/i],[MODEL,[VENDOR,FACEBOOK],[TYPE,XR]],[/mobile vr; rv.+firefox/i],[[TYPE,XR]],[/(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i],[VENDOR,[TYPE,EMBEDDED]],[/(aeobc)\\b/i],[MODEL,[VENDOR,AMAZON],[TYPE,EMBEDDED]],[/(homepod).+mac os/i],[MODEL,[VENDOR,APPLE],[TYPE,EMBEDDED]],[/windows iot/i],[[TYPE,EMBEDDED]],[/droid.+; ([\\w- ]+) (4k|android|smart|google)[- ]?tv/i],[MODEL,[TYPE,SMARTTV]],[/\\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\\w ]+safari)\\b/i],[[TYPE,SMARTTV]],[/droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew|; hmsc).+?(mobile|vr|\\d) safari/i],[MODEL,[TYPE,strMapper,{mobile:\"Mobile\",xr:\"VR\",\"*\":TABLET}]],[/\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i],[[TYPE,TABLET]],[/(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i],[[TYPE,MOBILE]],[/droid .+?; ([\\w\\. -]+)( bui|\\))/i],[MODEL,[VENDOR,\"Generic\"]]],engine:[[/windows.+ edge\\/([\\w\\.]+)/i],[VERSION,[NAME,EDGE+\"HTML\"]],[/(arkweb)\\/([\\w\\.]+)/i],[NAME,VERSION],[/webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i],[VERSION,[NAME,\"Blink\"]],[/(presto)\\/([\\w\\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i,/ekioh(flow)\\/([\\w\\.]+)/i,/(khtml|tasman|links|dillo)[\\/ ]\\(?([\\w\\.]+)/i,/(icab)[\\/ ]([23]\\.[\\d\\.]+)/i,/\\b(libweb)/i],[NAME,VERSION],[/ladybird\\//i],[[NAME,\"LibWeb\"]],[/rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i],[VERSION,NAME]],os:[[/(windows nt) (6\\.[23]); arm/i],[[NAME,/N/,\"R\"],[VERSION,strMapper,windowsVersionMap]],[/(windows (?:phone|mobile|iot))(?: os)?[\\/ ]?([\\d\\.]*( se)?)/i,/(windows)[\\/ ](1[01]|2000|3\\.1|7|8(\\.1)?|9[58]|me|server 20\\d\\d( r2)?|vista|xp)/i],[NAME,VERSION],[/windows nt ?([\\d\\.\\)]*)(?!.+xbox)/i,/\\bwin(?=3| ?9|n)(?:nt| 9x )?([\\d\\.;]*)/i],[[VERSION,/(;|\\))/g,\"\",strMapper,windowsVersionMap],[NAME,WINDOWS]],[/(windows ce)\\/?([\\d\\.]*)/i],[NAME,VERSION],[/[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i,/(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\\/ ]([\\w\\.]+)/i,/\\btvos ?([\\w\\.]+)/i,/cfnetwork\\/.+darwin/i],[[VERSION,/_/g,\".\"],[NAME,\"iOS\"]],[/(mac os x) ?([\\w\\. ]*)/i,/(macintosh|mac_powerpc\\b)(?!.+(haiku|morphos))/i],[[NAME,\"macOS\"],[VERSION,/_/g,\".\"]],[/android ([\\d\\.]+).*crkey/i],[VERSION,[NAME,CHROMECAST+\" Android\"]],[/fuchsia.*crkey\\/([\\d\\.]+)/i],[VERSION,[NAME,CHROMECAST+\" Fuchsia\"]],[/crkey\\/([\\d\\.]+).*devicetype\\/smartspeaker/i],[VERSION,[NAME,CHROMECAST+\" SmartSpeaker\"]],[/linux.*crkey\\/([\\d\\.]+)/i],[VERSION,[NAME,CHROMECAST+\" Linux\"]],[/crkey\\/([\\d\\.]+)/i],[VERSION,[NAME,CHROMECAST]],[/droid ([\\w\\.]+)\\b.+(android[- ]x86)/i],[VERSION,NAME],[/(ubuntu) ([\\w\\.]+) like android/i],[[NAME,/(.+)/,\"$1 Touch\"],VERSION],[/(harmonyos)[\\/ ]?([\\d\\.]*)/i,/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\\w*[-\\/\\.; ]?([\\d\\.]*)/i],[NAME,VERSION],[/\\(bb(10);/i],[VERSION,[NAME,BLACKBERRY]],[/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i],[VERSION,[NAME,\"Symbian\"]],[/mozilla\\/[\\d\\.]+ \\((?:mobile[;\\w ]*|tablet|tv|[^\\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\\w\\.]+)\\).+gecko\\//i],[VERSION,[NAME,FIREFOX+\" OS\"]],[/\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i,/webos(?:[ \\/]?|\\.tv-20(?=2[2-9]))(\\d[\\d\\.]*)/i],[VERSION,[NAME,\"webOS\"]],[/web0s;.+?(?:chr[o0]me|safari)\\/(\\d+)/i],[[VERSION,strMapper,{25:\"120\",24:\"108\",23:\"94\",22:\"87\",6:\"79\",5:\"68\",4:\"53\",3:\"38\",2:\"538\",1:\"537\",\"*\":\"TV\"}],[NAME,\"webOS\"]],[/watch(?: ?os[,\\/ ]|\\d,\\d\\/)([\\d\\.]+)/i],[VERSION,[NAME,\"watchOS\"]],[/cros [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i],[VERSION,[NAME,\"Chrome OS\"]],[/kepler ([\\w\\.]+); (aft|aeo)/i],[VERSION,[NAME,\"Vega OS\"]],[/(netrange)mmh/i,/(nettv)\\/(\\d+\\.[\\w\\.]+)/i,/(nintendo|playstation) (\\w+)/i,/(xbox); +xbox ([^\\);]+)/i,/(pico) .+os([\\w\\.]+)/i,/\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i,/linux.+(mint)[\\/\\(\\) ]?([\\w\\.]*)/i,/(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\\d\\.]*)/i,/([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\\/ ]?(?!chrom|package)([-\\w\\.]*)/i,/((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i,/\\b(aix)[; ]([1-9\\.]{0,4})/i,/(hurd|linux|morphos)(?: (?:arm|x86|ppc)\\w*| ?)([\\w\\.]*)/i,/(gnu) ?([\\w\\.]*)/i,/\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i,/(haiku) ?(r\\d)?/i],[NAME,VERSION],[/(sunos) ?([\\d\\.]*)/i],[[NAME,\"Solaris\"],VERSION],[/\\b(beos|os\\/2|amigaos|openvms|hp-ux|serenityos)/i,/(unix) ?([\\w\\.]*)/i],[NAME,VERSION]]};var defaultProps=function(){var props={init:{},isIgnore:{},isIgnoreRgx:{},toString:{}};setProps.call(props.init,[[BROWSER,[NAME,VERSION,MAJOR,TYPE]],[CPU,[ARCHITECTURE]],[DEVICE,[TYPE,MODEL,VENDOR]],[ENGINE,[NAME,VERSION]],[OS,[NAME,VERSION]]]);setProps.call(props.isIgnore,[[BROWSER,[VERSION,MAJOR]],[ENGINE,[VERSION]],[OS,[VERSION]]]);setProps.call(props.isIgnoreRgx,[[BROWSER,/ ?browser$/i],[OS,/ ?os$/i]]);setProps.call(props.toString,[[BROWSER,[NAME,VERSION]],[CPU,[ARCHITECTURE]],[DEVICE,[VENDOR,MODEL]],[ENGINE,[NAME,VERSION]],[OS,[NAME,VERSION]]]);return props}();var createIData=function(item,itemType){var init_props=defaultProps.init[itemType],is_ignoreProps=defaultProps.isIgnore[itemType]||0,is_ignoreRgx=defaultProps.isIgnoreRgx[itemType]||0,toString_props=defaultProps.toString[itemType]||0;function IData(){setProps.call(this,init_props)}IData.prototype.getItem=function(){return item};IData.prototype.withClientHints=function(){if(!NAVIGATOR_UADATA){return item.parseCH().get()}return NAVIGATOR_UADATA.getHighEntropyValues(CH_ALL_VALUES).then(function(res){return item.setCH(new UACHData(res,false)).parseCH().get()})};IData.prototype.withFeatureCheck=function(){return item.detectFeature().get()};if(itemType!=RESULT){IData.prototype.is=function(strToCheck){var is=false;for(var i in this){if(this.hasOwnProperty(i)&&!has(is_ignoreProps,i)&&lowerize(is_ignoreRgx?strip(is_ignoreRgx,this[i]):this[i])==lowerize(is_ignoreRgx?strip(is_ignoreRgx,strToCheck):strToCheck)){is=true;if(strToCheck!=TYPEOF.UNDEFINED)break}else if(strToCheck==TYPEOF.UNDEFINED&&is){is=!is;break}}return is};IData.prototype.toString=function(){var str=EMPTY;for(var i in toString_props){if(typeof this[toString_props[i]]!==TYPEOF.UNDEFINED){str+=(str?\" \":EMPTY)+this[toString_props[i]]}}return str||TYPEOF.UNDEFINED}}IData.prototype.then=function(cb){var that=this;var IDataResolve=function(){for(var prop in that){if(that.hasOwnProperty(prop)){this[prop]=that[prop]}}};IDataResolve.prototype={is:IData.prototype.is,toString:IData.prototype.toString,withClientHints:IData.prototype.withClientHints,withFeatureCheck:IData.prototype.withFeatureCheck};var resolveData=new IDataResolve;cb(resolveData);return resolveData};return new IData};function UACHData(uach,isHttpUACH){uach=uach||{};setProps.call(this,CH_ALL_VALUES);if(isHttpUACH){setProps.call(this,[[BRANDS,itemListToArray(uach[CH])],[FULLVERLIST,itemListToArray(uach[CH_FULL_VER_LIST])],[MOBILE,/\\?1/.test(uach[CH_MOBILE])],[MODEL,stripQuotes(uach[CH_MODEL])],[PLATFORM,stripQuotes(uach[CH_PLATFORM])],[PLATFORMVER,stripQuotes(uach[CH_PLATFORM_VER])],[ARCHITECTURE,stripQuotes(uach[CH_ARCH])],[FORMFACTORS,itemListToArray(uach[CH_FORM_FACTORS])],[BITNESS,stripQuotes(uach[CH_BITNESS])]])}else{for(var prop in uach){if(this.hasOwnProperty(prop)&&typeof uach[prop]!==TYPEOF.UNDEFINED)this[prop]=uach[prop]}}}function UAItem(itemType,ua,rgxMap,uaCH){setProps.call(this,[[\"itemType\",itemType],[\"ua\",ua],[\"uaCH\",uaCH],[\"rgxMap\",rgxMap],[\"data\",createIData(this,itemType)]]);return this}UAItem.prototype.get=function(prop){if(!prop)return this.data;return this.data.hasOwnProperty(prop)?this.data[prop]:undefined};UAItem.prototype.set=function(prop,val){this.data[prop]=val;return this};UAItem.prototype.setCH=function(ch){this.uaCH=ch;return this};UAItem.prototype.detectFeature=function(){if(NAVIGATOR&&NAVIGATOR.userAgent==this.ua){switch(this.itemType){case BROWSER:if(NAVIGATOR.brave&&typeof NAVIGATOR.brave.isBrave==TYPEOF.FUNCTION){this.set(NAME,\"Brave\")}break;case DEVICE:if(!this.get(TYPE)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[MOBILE]){this.set(TYPE,MOBILE)}if(this.get(MODEL)==\"Macintosh\"&&NAVIGATOR&&typeof NAVIGATOR.standalone!==TYPEOF.UNDEFINED&&NAVIGATOR.maxTouchPoints&&NAVIGATOR.maxTouchPoints>2){this.set(MODEL,\"iPad\").set(TYPE,TABLET)}break;case OS:if(!this.get(NAME)&&NAVIGATOR_UADATA&&NAVIGATOR_UADATA[PLATFORM]){this.set(NAME,NAVIGATOR_UADATA[PLATFORM])}break;case RESULT:var data=this.data;var detect=function(itemType){return data[itemType].getItem().detectFeature().get()};this.set(BROWSER,detect(BROWSER)).set(CPU,detect(CPU)).set(DEVICE,detect(DEVICE)).set(ENGINE,detect(ENGINE)).set(OS,detect(OS))}}return this};UAItem.prototype.parseUA=function(){if(this.itemType!=RESULT){rgxMapper.call(this.data,this.ua,this.rgxMap)}switch(this.itemType){case BROWSER:this.set(MAJOR,majorize(this.get(VERSION)));break;case OS:if(this.get(NAME)==\"iOS\"&&this.get(VERSION)==\"18.6\"){var realVersion=/\\) Version\\/([\\d\\.]+)/.exec(this.ua);if(realVersion&&parseInt(realVersion[1].substring(0,2),10)>=26){this.set(VERSION,realVersion[1])}}break}return this};UAItem.prototype.parseCH=function(){var uaCH=this.uaCH,rgxMap=this.rgxMap;switch(this.itemType){case BROWSER:case ENGINE:var brands=uaCH[FULLVERLIST]||uaCH[BRANDS],prevName;if(brands){for(var i=0;i<brands.length;i++){var brandName=brands[i].brand||brands[i],brandVersion=brands[i].version;if(this.itemType==BROWSER&&!/not.a.brand/i.test(brandName)&&(!prevName||/Chrom/.test(prevName)&&brandName!=CHROMIUM||prevName==EDGE&&/WebView2/.test(brandName))){brandName=strMapper(brandName,browserHintsMap);prevName=this.get(NAME);if(!(prevName&&!/Chrom/.test(prevName)&&/Chrom/.test(brandName))){this.set(NAME,brandName).set(VERSION,brandVersion).set(MAJOR,majorize(brandVersion))}prevName=brandName}if(this.itemType==ENGINE&&brandName==CHROMIUM){this.set(VERSION,brandVersion)}}}break;case CPU:var archName=uaCH[ARCHITECTURE];if(archName){if(archName&&uaCH[BITNESS]==\"64\")archName+=\"64\";rgxMapper.call(this.data,archName+\";\",rgxMap)}break;case DEVICE:if(uaCH[MOBILE]){this.set(TYPE,MOBILE)}if(uaCH[MODEL]){this.set(MODEL,uaCH[MODEL]);if(!this.get(TYPE)||!this.get(VENDOR)){var reParse={};rgxMapper.call(reParse,\"droid 9; \"+uaCH[MODEL]+\")\",rgxMap);if(!this.get(TYPE)&&!!reParse.type){this.set(TYPE,reParse.type)}if(!this.get(VENDOR)&&!!reParse.vendor){this.set(VENDOR,reParse.vendor)}}}if(uaCH[FORMFACTORS]){var ff;if(typeof uaCH[FORMFACTORS]!==\"string\"){var idx=0;while(!ff&&idx<uaCH[FORMFACTORS].length){ff=strMapper(uaCH[FORMFACTORS][idx++],formFactorsMap)}}else{ff=strMapper(uaCH[FORMFACTORS],formFactorsMap)}this.set(TYPE,ff)}break;case OS:var osName=uaCH[PLATFORM];if(osName){var osVersion=uaCH[PLATFORMVER];if(osName==WINDOWS)osVersion=parseInt(majorize(osVersion),10)>=13?\"11\":\"10\";this.set(NAME,osName).set(VERSION,osVersion)}if(this.get(NAME)==WINDOWS&&uaCH[MODEL]==\"Xbox\"){this.set(NAME,\"Xbox\").set(VERSION,undefined)}break;case RESULT:var data=this.data;var parse=function(itemType){return data[itemType].getItem().setCH(uaCH).parseCH().get()};this.set(BROWSER,parse(BROWSER)).set(CPU,parse(CPU)).set(DEVICE,parse(DEVICE)).set(ENGINE,parse(ENGINE)).set(OS,parse(OS))}return this};function UAParser(ua,extensions,headers){if(typeof ua===TYPEOF.OBJECT){if(isExtensions(ua,true)){if(typeof extensions===TYPEOF.OBJECT){headers=extensions}extensions=ua}else{headers=ua;extensions=undefined}ua=undefined}else if(typeof ua===TYPEOF.STRING&&!isExtensions(extensions,true)){headers=extensions;extensions=undefined}if(headers){if(typeof headers.append===TYPEOF.FUNCTION){var kv={};headers.forEach(function(v,k){kv[String(k).toLowerCase()]=v});headers=kv}else{var normalized={};for(var header in headers){if(headers.hasOwnProperty(header)){normalized[String(header).toLowerCase()]=headers[header]}}headers=normalized}}if(!(this instanceof UAParser)){return new UAParser(ua,extensions,headers).getResult()}var userAgent=typeof ua===TYPEOF.STRING?ua:headers&&headers[USER_AGENT]?headers[USER_AGENT]:NAVIGATOR&&NAVIGATOR.userAgent?NAVIGATOR.userAgent:EMPTY,httpUACH=new UACHData(headers,true),regexMap=extensions?extend(defaultRegexes,extensions):defaultRegexes,createItemFunc=function(itemType){if(itemType==RESULT){return function(){return new UAItem(itemType,userAgent,regexMap,httpUACH).set(\"ua\",userAgent).set(BROWSER,this.getBrowser()).set(CPU,this.getCPU()).set(DEVICE,this.getDevice()).set(ENGINE,this.getEngine()).set(OS,this.getOS()).get()}}else{return function(){return new UAItem(itemType,userAgent,regexMap[itemType],httpUACH).parseUA().get()}}};setProps.call(this,[[\"getBrowser\",createItemFunc(BROWSER)],[\"getCPU\",createItemFunc(CPU)],[\"getDevice\",createItemFunc(DEVICE)],[\"getEngine\",createItemFunc(ENGINE)],[\"getOS\",createItemFunc(OS)],[\"getResult\",createItemFunc(RESULT)],[\"getUA\",function(){return userAgent}],[\"setUA\",function(ua){if(isString(ua))userAgent=trim(ua,UA_MAX_LENGTH);return this}]]).setUA(userAgent);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR,TYPE]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);export{UAParser};"
  },
  {
    "path": "dist/ua-parser.pack.js",
    "content": "/* UAParser.js v2.0.9\n   Copyright © 2012-2026 Faisal Salman <f@faisalman.com>\n   AGPLv3 License */\n((i,c)=>{function A(i){for(var e={},t=0;t<i.length;t++)e[i[t].toUpperCase()]=i[t];return e}function B(i){return Ti(i)?Oi(/[^\\d\\.]/g,i).split(\".\")[0]:c}function H(i,e){if(i&&e)for(var t,o,r,a,s,n=0;n<e.length&&!a;){for(var w=e[n],b=e[n+1],d=t=0;d<w.length&&!a&&w[d];)if(a=w[d++].exec(i))for(o=0;o<b.length;o++)s=a[++t],typeof(r=b[o])===l.OBJECT&&0<r.length?2===r.length?typeof r[1]==l.FUNCTION?this[r[0]]=r[1].call(this,s):this[r[0]]=r[1]:3<=r.length&&(typeof r[1]!==l.FUNCTION||r[1].exec&&r[1].test?3==r.length?this[r[0]]=s?s.replace(r[1],r[2]):c:4==r.length?this[r[0]]=s?r[3].call(this,s.replace(r[1],r[2])):c:4<r.length&&(this[r[0]]=s?r[3].apply(this,[s.replace(r[1],r[2])].concat(r.slice(4))):c):3<r.length?this[r[0]]=s?r[1].apply(this,r.slice(2)):c:this[r[0]]=s?r[1].call(this,s,r[2]):c):this[r]=s||c;n+=2}}function p(i,e){for(var t in e)if(typeof e[t]===l.OBJECT&&0<e[t].length){for(var o=0;o<e[t].length;o++)if(Ei(e[t][o],i))return\"?\"===t?c:t}else if(Ei(e[t],i))return\"?\"===t?c:t;return e.hasOwnProperty(\"*\")?e[\"*\"]:i}function M(e,i){var t=Ai.init[i],o=Ai.isIgnore[i]||0,r=Ai.isIgnoreRgx[i]||0,a=Ai.toString[i]||0;function s(){D.call(this,t)}return s.prototype.getItem=function(){return e},s.prototype.withClientHints=function(){return _?_.getHighEntropyValues(oi).then(function(i){return e.setCH(new Bi(i,!1)).parseCH().get()}):e.parseCH().get()},s.prototype.withFeatureCheck=function(){return e.detectFeature().get()},i!=v&&(s.prototype.is=function(i){var e,t=!1;for(e in this)if(this.hasOwnProperty(e)&&!Ei(o,e)&&q(r?Oi(r,this[e]):this[e])==q(r?Oi(r,i):i)){if(t=!0,i!=l.UNDEFINED)break}else if(i==l.UNDEFINED&&t){t=!t;break}return t},s.prototype.toString=function(){var i,e=d;for(i in a)typeof this[a[i]]!==l.UNDEFINED&&(e+=(e?\" \":d)+this[a[i]]);return e||l.UNDEFINED}),s.prototype.then=function(i){function e(){for(var i in t)t.hasOwnProperty(i)&&(this[i]=t[i])}var t=this,o=(e.prototype={is:s.prototype.is,toString:s.prototype.toString,withClientHints:s.prototype.withClientHints,withFeatureCheck:s.prototype.withFeatureCheck},new e);return i(o),o},new s}var V=\"user-agent\",d=\"\",l={FUNCTION:\"function\",OBJECT:\"object\",STRING:\"string\",UNDEFINED:\"undefined\"},h=\"browser\",u=\"cpu\",m=\"device\",f=\"engine\",g=\"os\",v=\"result\",k=\"name\",x=\"type\",y=\"vendor\",C=\"version\",N=\"architecture\",j=\"major\",E=\"model\",P=\"console\",S=\"mobile\",t=\"tablet\",e=\"smarttv\",o=\"wearable\",R=\"xr\",G=\"embedded\",r=\"inapp\",L=\"brands\",T=\"formFactors\",$=\"fullVersionList\",I=\"platform\",W=\"platformVersion\",J=\"bitness\",a=\"sec-ch-ua\",X=a+\"-full-version-list\",Y=a+\"-arch\",Z=a+\"-\"+J,Q=a+\"-form-factors\",K=a+\"-\"+S,ii=a+\"-\"+E,ei=a+\"-\"+I,ti=ei+\"-version\",oi=[L,$,S,E,I,W,N,T,J],ri=\"Amazon\",s=\"Apple\",ai=\"ASUS\",si=\"BlackBerry\",n=\"Google\",ni=\"Huawei\",wi=\"Lenovo\",bi=\"Honor\",di=\"Microsoft\",li=\"Motorola\",ci=\"OnePlus\",pi=\"OPPO\",hi=\"Samsung\",ui=\"Sony\",mi=\"Xiaomi\",fi=\"Zebra\",gi=\"Chromium\",w=\"Chromecast\",vi=\"Edge\",ki=\"Firefox\",b=\"Opera\",xi=\"Facebook\",O=\"Mobile \",yi=\" Browser\",Ci=\"Windows\",Ni=typeof i!==l.UNDEFINED,U=Ni&&i.navigator?i.navigator:c,_=U&&U.userAgentData?U.userAgentData:c,Ei=function(i,e){if(typeof i===l.OBJECT&&0<i.length){for(var t in i)if(q(e)==q(i[t]))return!0;return!1}return!!Ti(i)&&q(e)==q(i)},Si=function(i,e){for(var t in i)return/^(browser|cpu|device|engine|os)$/.test(t)||!!e&&Si(i[t])},Ti=function(i){return typeof i===l.STRING},Ii=function(i){if(!i)return c;for(var e,t=[],o=Oi(/\\\\?\\\"/g,i).split(\",\"),r=0;r<o.length;r++)-1<o[r].indexOf(\";\")?(e=_i(o[r]).split(\";v=\"),t[r]={brand:e[0],version:e[1]}):t[r]=_i(o[r]);return t},q=function(i){return Ti(i)?i.toLowerCase():i},D=function(i){for(var e in i)i.hasOwnProperty(e)&&(typeof(e=i[e])==l.OBJECT&&2==e.length?this[e[0]]=e[1]:this[e]=c);return this},Oi=function(i,e){return Ti(e)?e.replace(i,d):e},Ui=function(i){return Oi(/\\\\?\\\"/g,i)},_i=function(i,e){return i=Oi(/^\\s\\s*/,String(i)),typeof e===l.UNDEFINED?i:i.substring(0,e)},qi={ME:\"4.90\",\"NT 3.51\":\"3.51\",\"NT 4.0\":\"4.0\",2e3:[\"5.0\",\"5.01\"],XP:[\"5.1\",\"5.2\"],Vista:\"6.0\",7:\"6.1\",8:\"6.2\",8.1:\"6.3\",10:[\"6.4\",\"10.0\"],NT:\"\"},Di={embedded:\"Automotive\",mobile:\"Mobile\",tablet:[\"Tablet\",\"EInk\"],smarttv:\"TV\",wearable:\"Watch\",xr:[\"VR\",\"XR\"],\"?\":[\"Desktop\",\"Unknown\"],\"*\":c},Fi={Chrome:\"Google Chrome\",Edge:\"Microsoft Edge\",\"Edge WebView2\":\"Microsoft Edge WebView2\",\"Chrome WebView\":\"Android WebView\",\"Chrome Headless\":\"HeadlessChrome\",\"Huawei Browser\":\"HuaweiBrowser\",\"MIUI Browser\":\"Miui Browser\",\"Opera Mobi\":\"OperaMobile\",Yandex:\"YaBrowser\"},zi={browser:[[/\\b(?:crmo|crios)\\/([\\w\\.]+)/i],[C,[k,O+\"Chrome\"]],[/webview.+edge\\/([\\w\\.]+)/i],[C,[k,vi+\" WebView\"]],[/edg(?:e|ios|a)?\\/([\\w\\.]+)/i],[C,[k,\"Edge\"]],[/(opera mini)\\/([-\\w\\.]+)/i,/(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i,/(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i],[k,C],[/opios[\\/ ]+([\\w\\.]+)/i],[C,[k,b+\" Mini\"]],[/\\bop(?:rg)?x\\/([\\w\\.]+)/i],[C,[k,b+\" GX\"]],[/\\bopr\\/([\\w\\.]+)/i],[C,[k,b]],[/\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i],[C,[k,\"Baidu\"]],[/\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i],[C,[k,\"Maxthon\"]],[/(kindle)\\/([\\w\\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i,/(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i,/(?:ms|\\()(ie) ([\\w\\.]+)/i,/(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\\/v?([-\\w\\.]+)/i,/(brave)(?: chrome)?\\/([\\d\\.]+)/i,/(aloha|heytap|ovi|115|surf|qwant)browser\\/([\\d\\.]+)/i,/(qwant)(?:ios|mobile)\\/([\\d\\.]+)/i,/(ecosia|weibo)(?:__| \\w+@)([\\d\\.]+)/i],[k,C],[/quark(?:pc)?\\/([-\\w\\.]+)/i],[C,[k,\"Quark\"]],[/\\bddg\\/([\\w\\.]+)/i],[C,[k,\"DuckDuckGo\"]],[/(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i],[C,[k,\"UCBrowser\"]],[/microm.+\\bqbcore\\/([\\w\\.]+)/i,/\\bqbcore\\/([\\w\\.]+).+microm/i,/micromessenger\\/([\\w\\.]+)/i],[C,[k,\"WeChat\"]],[/konqueror\\/([\\w\\.]+)/i],[C,[k,\"Konqueror\"]],[/trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i],[C,[k,\"IE\"]],[/ya(?:search)?browser\\/([\\w\\.]+)/i],[C,[k,\"Yandex\"]],[/slbrowser\\/([\\w\\.]+)/i],[C,[k,\"Smart \"+wi+yi]],[/(av(?:ast|g|ira))\\/([\\w\\.]+)/i],[[k,/(.+)/,\"$1 Secure\"+yi],C],[/norton\\/([\\w\\.]+)/i],[C,[k,\"Norton Private\"+yi]],[/\\bfocus\\/([\\w\\.]+)/i],[C,[k,ki+\" Focus\"]],[/ mms\\/([\\w\\.]+)$/i],[C,[k,b+\" Neon\"]],[/ opt\\/([\\w\\.]+)$/i],[C,[k,b+\" Touch\"]],[/coc_coc\\w+\\/([\\w\\.]+)/i],[C,[k,\"Coc Coc\"]],[/dolfin\\/([\\w\\.]+)/i],[C,[k,\"Dolphin\"]],[/coast\\/([\\w\\.]+)/i],[C,[k,b+\" Coast\"]],[/miuibrowser\\/([\\w\\.]+)/i],[C,[k,\"MIUI\"+yi]],[/fxios\\/([\\w\\.-]+)/i],[C,[k,O+ki]],[/\\bqihoobrowser\\/?([\\w\\.]*)/i],[C,[k,\"360\"]],[/\\b(qq)\\/([\\w\\.]+)/i],[[k,/(.+)/,\"$1Browser\"],C],[/(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i],[[k,/(.+)/,\"$1\"+yi],C],[/samsungbrowser\\/([\\w\\.]+)/i],[C,[k,hi+\" Internet\"]],[/metasr[\\/ ]?([\\d\\.]+)/i],[C,[k,\"Sogou Explorer\"]],[/(sogou)mo\\w+\\/([\\d\\.]+)/i],[[k,\"Sogou Mobile\"],C],[/(electron)\\/([\\w\\.]+) safari/i,/(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i,/m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i],[k,C],[/(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i],[k],[/ome\\/([\\w\\.]+).+(iron(?= saf)|360(?=[es]e$))/i],[C,k],[/((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i],[[k,xi],C,[x,r]],[/(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i,/(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i,/(daum)apps[\\/ ]([\\w\\.]+)/i,/safari (line)\\/([\\w\\.]+)/i,/\\b(line)\\/([\\w\\.]+)\\/iab/i,/(alipay)client\\/([\\w\\.]+)/i,/(twitter)(?:and| f.+e\\/([\\w\\.]+))/i,/(bing)(?:web|sapphire)\\/([\\w\\.]+)/i,/(instagram|snapchat|klarna)[\\/ ]([-\\w\\.]+)/i],[k,C,[x,r]],[/\\bgsa\\/([\\w\\.]+) .*safari\\//i],[C,[k,\"GSA\"],[x,r]],[/(?:musical_ly|trill)(?:.+app_?version\\/|_)([\\w\\.]+)/i],[C,[k,\"TikTok\"],[x,r]],[/\\[(linkedin)app\\]/i],[k,[x,r]],[/(zalo(?:app)?)[\\/\\sa-z]*([\\w\\.-]+)/i],[[k,/(.+)/,\"Zalo\"],C,[x,r]],[/(chromium)[\\/ ]([-\\w\\.]+)/i],[k,C],[/ome-(lighthouse)$/i],[k,[x,\"fetcher\"]],[/headlesschrome(?:\\/([\\w\\.]+)| )/i],[C,[k,\"Chrome Headless\"]],[/wv\\).+chrome\\/([\\w\\.]+).+edgw\\//i],[C,[k,vi+\" WebView2\"]],[/ wv\\).+(chrome)\\/([\\w\\.]+)/i],[[k,\"Chrome WebView\"],C],[/droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i],[C,[k,\"Android\"+yi]],[/chrome\\/([\\w\\.]+) mobile/i],[C,[k,O+\"Chrome\"]],[/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i],[k,C],[/version\\/([\\w\\.\\,]+) .*mobile(?:\\/\\w+ | ?)safari/i],[C,[k,O+\"Safari\"]],[/iphone .*mobile(?:\\/\\w+ | ?)safari/i],[[k,O+\"Safari\"]],[/version\\/([\\w\\.\\,]+) .*(safari)/i],[C,k],[/webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i],[k,[C,\"1\"]],[/(webkit|khtml)\\/([\\w\\.]+)/i],[k,C],[/(?:mobile|tablet);.*(firefox)\\/([\\w\\.-]+)/i],[[k,O+ki],C],[/(navigator|netscape\\d?)\\/([-\\w\\.]+)/i],[[k,\"Netscape\"],C],[/(wolvic|librewolf)\\/([\\w\\.]+)/i],[k,C],[/mobile vr; rv:([\\w\\.]+)\\).+firefox/i],[C,[k,ki+\" Reality\"]],[/ekiohf.+(flow)\\/([\\w\\.]+)/i,/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\\/([-\\w\\.]+)$/i,/(firefox)\\/([\\w\\.]+)/i,/(mozilla)\\/([\\w\\.]+(?= .+rv\\:.+gecko\\/\\d+)|[0-4][\\w\\.]+(?!.+compatible))/i,/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,/\\b(links) \\(([\\w\\.]+)/i],[k,[C,/_/g,\".\"]],[/(cobalt)\\/([\\w\\.]+)/i],[k,[C,/[^\\d\\.]+./,d]]],cpu:[[/\\b((amd|x|x86[-_]?|wow|win)64)\\b/i],[[N,\"amd64\"]],[/(ia32(?=;))/i,/\\b((i[346]|x)86)(pc)?\\b/i],[[N,\"ia32\"]],[/\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i],[[N,\"arm64\"]],[/\\b(arm(v[67])?ht?n?[fl]p?)\\b/i],[[N,\"armhf\"]],[/( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i],[[N,\"arm\"]],[/ sun4\\w[;\\)]/i],[[N,\"sparc\"]],[/\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i,/((ppc|powerpc)(64)?)( mac|;|\\))/i,/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i],[[N,/ower/,d,q]],[/mc680.0/i],[[N,\"68k\"]],[/winnt.+\\[axp/i],[[N,\"alpha\"]]],device:[[/\\b(sch-i[89]0\\d|shw-m380s|sm-[ptx]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus 10)/i],[E,[y,hi],[x,t]],[/\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,/samsung[- ]((?!sm-[lr]|browser)[-\\w]+)/i,/sec-(sgh\\w+)/i],[E,[y,hi],[x,S]],[/(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)[\\/\\);]/i],[E,[y,s],[x,S]],[/\\b(?:ios|apple\\w+)\\/.+[\\(\\/](ipad)/i,/\\b(ipad)[\\d,]*[;\\] ].+(mac |i(pad)?)os/i],[E,[y,s],[x,t]],[/(macintosh);/i],[E,[y,s]],[/\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i],[E,[y,\"Sharp\"],[x,S]],[/\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i],[E,[y,bi],[x,t]],[/honor([-\\w ]+)[;\\)]/i],[E,[y,bi],[x,S]],[/\\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\\w\\. ]*(?= bui|\\)))\\b(?!.+d\\/s)/i],[E,[y,ni],[x,t]],[/(?:huawei) ?([-\\w ]+)[;\\)]/i,/\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][\\dc][adnt]?)\\b(?!.+d\\/s)/i],[E,[y,ni],[x,S]],[/oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,/\\b(?:xiao)?((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i],[[E,/_/g,\" \"],[y,mi],[x,t]],[/\\b; (\\w+) build\\/hm\\1/i,/\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i,/oid[^\\)]+; (redmi[\\-_ ]?(?:note|k)?[\\w_ ]+|m?[12]\\d[01]\\d\\w{3,6}|poco[\\w ]+|(shark )?\\w{3}-[ah]0|qin ?[1-3](s\\+|ultra| pro)?)( bui|; wv|\\))/i,/\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\\d{0,2}\\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\\))/i,/ ([\\w ]+) miui\\/v?\\d/i],[[E,/_/g,\" \"],[y,mi],[x,S]],[/droid.+; (cph2[3-6]\\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\\d|p[g-l]\\w[1m]10)\\b/i,/(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i],[E,[y,ci],[x,S]],[/; (\\w+) bui.+ oppo/i,/\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i],[E,[y,pi],[x,S]],[/\\b(opd2(\\d{3}a?))(?: bui|\\))/i],[E,[y,p,{OnePlus:[\"203\",\"304\",\"403\",\"404\",\"413\",\"415\"],\"*\":pi}],[x,t]],[/(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\\w\\+ ]*)(?: bui|\\))/i],[E,[y,\"BLU\"],[x,S]],[/; vivo (\\w+)(?: bui|\\))/i,/\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i],[E,[y,\"Vivo\"],[x,S]],[/\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i],[E,[y,\"Realme\"],[x,S]],[/(ideatab[-\\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\\d{3,4}(?:f[cu]|xu|[av])|yt\\d?-[jx]?\\d+[lfmx])( bui|;|\\)|\\/)/i,/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i],[E,[y,wi],[x,t]],[/lenovo[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i],[E,[y,wi],[x,S]],[/\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,/\\bmot(?:orola)?[- ]([\\w\\s]+)(\\)| bui)/i,/((?:moto(?! 360)[-\\w\\(\\) ]+|xt\\d{3,4}[cgkosw\\+]?[-\\d]*|nexus 6)(?= bui|\\)))/i],[E,[y,li],[x,S]],[/\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i],[E,[y,li],[x,t]],[/\\b(?:lg)?([vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i],[E,[y,\"LG\"],[x,t]],[/(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,/\\blg[-e;\\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\\w+)/i,/\\blg-?([\\d\\w]+) bui/i],[E,[y,\"LG\"],[x,S]],[/(nokia) (t[12][01])/i],[y,E,[x,t]],[/(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,/nokia[-_ ]?(([-\\w\\. ]*?))( bui|\\)|;|\\/)/i],[[E,/_/g,\" \"],[x,S],[y,\"Nokia\"]],[/(pixel (c|tablet))\\b/i],[E,[y,n],[x,t]],[/droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\\d ]*a?( pro)?( xl)?( fold)?( \\(5g\\))?)( bui|\\))/i],[E,[y,n],[x,S]],[/(google) (pixelbook( go)?)/i],[y,E],[/droid.+; (a?\\d[0-2]{2}so|[c-g]\\d{4}|so[-gl]\\w+|xq-\\w\\w\\d\\d)(?= bui|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i],[E,[y,ui],[x,S]],[/sony tablet [ps]/i,/\\b(?:sony)?sgp\\w+(?: bui|\\))/i],[[E,\"Xperia Tablet\"],[y,ui],[x,t]],[/(alexa)webm/i,/(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i,/(kf[a-z]+)( bui|\\)).+silk\\//i],[E,[y,ri],[x,t]],[/((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i],[[E,/(.+)/g,\"Fire Phone $1\"],[y,ri],[x,S]],[/(playbook);[-\\w\\),; ]+(rim)/i],[E,y,[x,t]],[/\\b((?:bb[a-f]|st[hv])100-\\d)/i,/(?:blackberry|\\(bb10;) (\\w+)/i],[E,[y,si],[x,S]],[/(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i],[E,[y,ai],[x,t]],[/ (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i],[E,[y,ai],[x,S]],[/(nexus 9)/i],[E,[y,\"HTC\"],[x,t]],[/(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i,/(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,/(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i],[y,[E,/_/g,\" \"],[x,S]],[/tcl (xess p17aa)/i,/droid [\\w\\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\\w(\\w|\\w\\w))?(\\)| bui)/i],[E,[y,\"TCL\"],[x,t]],[/droid [\\w\\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\\w(\\w|\\w\\w))?(\\)| bui)/i],[E,[y,\"TCL\"],[x,S]],[/(itel) ((\\w+))/i],[[y,q],E,[x,p,{tablet:[\"p10001l\",\"w7001\"],\"*\":\"mobile\"}]],[/droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i],[E,[y,\"Acer\"],[x,t]],[/droid.+; (m[1-5] note) bui/i,/\\bmz-([-\\w]{2,})/i],[E,[y,\"Meizu\"],[x,S]],[/; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i],[E,[y,\"Ulefone\"],[x,S]],[/; (energy ?\\w+)(?: bui|\\))/i,/; energizer ([\\w ]+)(?: bui|\\))/i],[E,[y,\"Energizer\"],[x,S]],[/; cat (b35);/i,/; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i],[E,[y,\"Cat\"],[x,S]],[/((?:new )?andromax[\\w- ]+)(?: bui|\\))/i],[E,[y,\"Smartfren\"],[x,S]],[/droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i],[E,[y,\"Nothing\"],[x,S]],[/; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,/archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i],[E,[y,\"Archos\"],[x,t]],[/archos ([\\w ]+)( b|\\))/i,/; (ac[3-6]\\d\\w{2,8})( b|\\))/i],[E,[y,\"Archos\"],[x,S]],[/; (n159v)/i],[E,[y,\"HMD\"],[x,S]],[/(imo) (tab \\w+)/i,/(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i],[y,E,[x,t]],[/(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\\w\\+ ]+?)(?: bui|\\)|; r)/i,/(hp) ([\\w ]+\\w)/i,/(microsoft); (lumia[\\w ]+)/i,/(oppo) ?([\\w ]+) bui/i,/(hisense) ([ehv][\\w ]+)\\)/i,/droid[^;]+; (philips)[_ ]([sv-x][\\d]{3,4}[xz]?)/i],[y,E,[x,S]],[/(kobo)\\s(ereader|touch)/i,/(hp).+(touchpad(?!.+tablet)|tablet)/i,/(kindle)\\/([\\w\\.]+)/i],[y,E,[x,t]],[/(surface duo)/i],[E,[y,di],[x,t]],[/droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i],[E,[y,\"Fairphone\"],[x,S]],[/((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i],[E,[y,\"Nvidia\"],[x,t]],[/(sprint) (\\w+)/i],[y,E,[x,S]],[/(kin\\.[onetw]{3})/i],[[E,/\\./g,\" \"],[y,di],[x,S]],[/droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i],[E,[y,fi],[x,t]],[/droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i],[E,[y,fi],[x,S]],[/(philips)[\\w ]+tv/i,/smart-tv.+(samsung)/i],[y,[x,e]],[/hbbtv.+maple;(\\d+)/i],[[E,/^/,\"SmartTV\"],[y,hi],[x,e]],[/(vizio)(?: |.+model\\/)(\\w+-\\w+)/i,/tcast.+(lg)e?. ([-\\w]+)/i],[y,E,[x,e]],[/(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i],[[y,\"LG\"],[x,e]],[/(apple) ?tv/i],[y,[E,s+\" TV\"],[x,e]],[/crkey.*devicetype\\/chromecast/i],[[E,w+\" Third Generation\"],[y,n],[x,e]],[/crkey.*devicetype\\/([^/]*)/i],[[E,/^/,\"Chromecast \"],[y,n],[x,e]],[/fuchsia.*crkey/i],[[E,w+\" Nest Hub\"],[y,n],[x,e]],[/crkey/i],[[E,w],[y,n],[x,e]],[/(portaltv)/i],[E,[y,xi],[x,e]],[/droid.+aft(\\w+)( bui|\\))/i],[E,[y,ri],[x,e]],[/(shield \\w+ tv)/i],[E,[y,\"Nvidia\"],[x,e]],[/\\(dtv[\\);].+(aquos)/i,/(aquos-tv[\\w ]+)\\)/i],[E,[y,\"Sharp\"],[x,e]],[/(bravia[\\w ]+)( bui|\\))/i],[E,[y,ui],[x,e]],[/(mi(tv|box)-?\\w+) bui/i],[E,[y,mi],[x,e]],[/Hbbtv.*(technisat) (.*);/i],[y,E,[x,e]],[/\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i,/hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i],[[y,/.+\\/(\\w+)/,\"$1\",p,{LG:\"lge\"}],[E,_i],[x,e]],[/(playstation \\w+)/i],[E,[y,ui],[x,P]],[/\\b(xbox(?: one)?(?!; xbox))[\\); ]/i],[E,[y,di],[x,P]],[/(ouya)/i,/(nintendo) (\\w+)/i,/(retroid) (pocket ([^\\)]+))/i,/(valve).+(steam deck)/i,/droid.+; ((shield|rgcube|gr0006))( bui|\\))/i],[[y,p,{Nvidia:\"Shield\",Anbernic:\"RGCUBE\",Logitech:\"GR0006\"}],E,[x,P]],[/\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i],[E,[y,hi],[x,o]],[/((pebble))app/i,/(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i],[y,E,[x,o]],[/(ow(?:19|20)?we?[1-3]{1,3})/i],[E,[y,pi],[x,o]],[/(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i],[E,[y,s],[x,o]],[/(opwwe\\d{3})/i],[E,[y,ci],[x,o]],[/(moto 360)/i],[E,[y,li],[x,o]],[/(smartwatch 3)/i],[E,[y,ui],[x,o]],[/(g watch r)/i],[E,[y,\"LG\"],[x,o]],[/droid.+; (wt63?0{2,3})\\)/i],[E,[y,fi],[x,o]],[/droid.+; (glass) \\d/i],[E,[y,n],[x,R]],[/(pico) ([\\w ]+) os\\d/i],[y,E,[x,R]],[/(quest( \\d| pro)?s?).+vr/i],[E,[y,xi],[x,R]],[/mobile vr; rv.+firefox/i],[[x,R]],[/(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i],[y,[x,G]],[/(aeobc)\\b/i],[E,[y,ri],[x,G]],[/(homepod).+mac os/i],[E,[y,s],[x,G]],[/windows iot/i],[[x,G]],[/droid.+; ([\\w- ]+) (4k|android|smart|google)[- ]?tv/i],[E,[x,e]],[/\\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\\w ]+safari)\\b/i],[[x,e]],[/droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew|; hmsc).+?(mobile|vr|\\d) safari/i],[E,[x,p,{mobile:\"Mobile\",xr:\"VR\",\"*\":t}]],[/\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i],[[x,t]],[/(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i],[[x,S]],[/droid .+?; ([\\w\\. -]+)( bui|\\))/i],[E,[y,\"Generic\"]]],engine:[[/windows.+ edge\\/([\\w\\.]+)/i],[C,[k,vi+\"HTML\"]],[/(arkweb)\\/([\\w\\.]+)/i],[k,C],[/webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i],[C,[k,\"Blink\"]],[/(presto)\\/([\\w\\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i,/ekioh(flow)\\/([\\w\\.]+)/i,/(khtml|tasman|links|dillo)[\\/ ]\\(?([\\w\\.]+)/i,/(icab)[\\/ ]([23]\\.[\\d\\.]+)/i,/\\b(libweb)/i],[k,C],[/ladybird\\//i],[[k,\"LibWeb\"]],[/rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i],[C,k]],os:[[/(windows nt) (6\\.[23]); arm/i],[[k,/N/,\"R\"],[C,p,qi]],[/(windows (?:phone|mobile|iot))(?: os)?[\\/ ]?([\\d\\.]*( se)?)/i,/(windows)[\\/ ](1[01]|2000|3\\.1|7|8(\\.1)?|9[58]|me|server 20\\d\\d( r2)?|vista|xp)/i],[k,C],[/windows nt ?([\\d\\.\\)]*)(?!.+xbox)/i,/\\bwin(?=3| ?9|n)(?:nt| 9x )?([\\d\\.;]*)/i],[[C,/(;|\\))/g,\"\",p,qi],[k,Ci]],[/(windows ce)\\/?([\\d\\.]*)/i],[k,C],[/[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i,/(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\\/ ]([\\w\\.]+)/i,/\\btvos ?([\\w\\.]+)/i,/cfnetwork\\/.+darwin/i],[[C,/_/g,\".\"],[k,\"iOS\"]],[/(mac os x) ?([\\w\\. ]*)/i,/(macintosh|mac_powerpc\\b)(?!.+(haiku|morphos))/i],[[k,\"macOS\"],[C,/_/g,\".\"]],[/android ([\\d\\.]+).*crkey/i],[C,[k,w+\" Android\"]],[/fuchsia.*crkey\\/([\\d\\.]+)/i],[C,[k,w+\" Fuchsia\"]],[/crkey\\/([\\d\\.]+).*devicetype\\/smartspeaker/i],[C,[k,w+\" SmartSpeaker\"]],[/linux.*crkey\\/([\\d\\.]+)/i],[C,[k,w+\" Linux\"]],[/crkey\\/([\\d\\.]+)/i],[C,[k,w]],[/droid ([\\w\\.]+)\\b.+(android[- ]x86)/i],[C,k],[/(ubuntu) ([\\w\\.]+) like android/i],[[k,/(.+)/,\"$1 Touch\"],C],[/(harmonyos)[\\/ ]?([\\d\\.]*)/i,/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\\w*[-\\/\\.; ]?([\\d\\.]*)/i],[k,C],[/\\(bb(10);/i],[C,[k,si]],[/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i],[C,[k,\"Symbian\"]],[/mozilla\\/[\\d\\.]+ \\((?:mobile[;\\w ]*|tablet|tv|[^\\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\\w\\.]+)\\).+gecko\\//i],[C,[k,ki+\" OS\"]],[/\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i,/webos(?:[ \\/]?|\\.tv-20(?=2[2-9]))(\\d[\\d\\.]*)/i],[C,[k,\"webOS\"]],[/web0s;.+?(?:chr[o0]me|safari)\\/(\\d+)/i],[[C,p,{25:\"120\",24:\"108\",23:\"94\",22:\"87\",6:\"79\",5:\"68\",4:\"53\",3:\"38\",2:\"538\",1:\"537\",\"*\":\"TV\"}],[k,\"webOS\"]],[/watch(?: ?os[,\\/ ]|\\d,\\d\\/)([\\d\\.]+)/i],[C,[k,\"watchOS\"]],[/cros [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i],[C,[k,\"Chrome OS\"]],[/kepler ([\\w\\.]+); (aft|aeo)/i],[C,[k,\"Vega OS\"]],[/(netrange)mmh/i,/(nettv)\\/(\\d+\\.[\\w\\.]+)/i,/(nintendo|playstation) (\\w+)/i,/(xbox); +xbox ([^\\);]+)/i,/(pico) .+os([\\w\\.]+)/i,/\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i,/linux.+(mint)[\\/\\(\\) ]?([\\w\\.]*)/i,/(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\\d\\.]*)/i,/([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\\/ ]?(?!chrom|package)([-\\w\\.]*)/i,/((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i,/\\b(aix)[; ]([1-9\\.]{0,4})/i,/(hurd|linux|morphos)(?: (?:arm|x86|ppc)\\w*| ?)([\\w\\.]*)/i,/(gnu) ?([\\w\\.]*)/i,/\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i,/(haiku) ?(r\\d)?/i],[k,C],[/(sunos) ?([\\d\\.]*)/i],[[k,\"Solaris\"],C],[/\\b(beos|os\\/2|amigaos|openvms|hp-ux|serenityos)/i,/(unix) ?([\\w\\.]*)/i],[k,C]]},Ai=(b={init:{},isIgnore:{},isIgnoreRgx:{},toString:{}},D.call(b.init,[[h,[k,C,j,x]],[u,[N]],[m,[x,E,y]],[f,[k,C]],[g,[k,C]]]),D.call(b.isIgnore,[[h,[C,j]],[f,[C]],[g,[C]]]),D.call(b.isIgnoreRgx,[[h,/ ?browser$/i],[g,/ ?os$/i]]),D.call(b.toString,[[h,[k,C]],[u,[N]],[m,[y,E]],[f,[k,C]],[g,[k,C]]]),b);function Bi(i,e){if(i=i||{},D.call(this,oi),e)D.call(this,[[L,Ii(i[a])],[$,Ii(i[X])],[S,/\\?1/.test(i[K])],[E,Ui(i[ii])],[I,Ui(i[ei])],[W,Ui(i[ti])],[N,Ui(i[Y])],[T,Ii(i[Q])],[J,Ui(i[Z])]]);else for(var t in i)this.hasOwnProperty(t)&&typeof i[t]!==l.UNDEFINED&&(this[t]=i[t])}function F(i,e,t,o){return D.call(this,[[\"itemType\",i],[\"ua\",e],[\"uaCH\",o],[\"rgxMap\",t],[\"data\",M(this,i)]]),this}function z(i,e,t){if(typeof i===l.OBJECT?(e=Si(i,!0)?(typeof e===l.OBJECT&&(t=e),i):(t=i,c),i=c):typeof i!==l.STRING||Si(e,!0)||(t=e,e=c),t)if(typeof t.append===l.FUNCTION){var o={};t.forEach(function(i,e){o[String(e).toLowerCase()]=i}),t=o}else{var r,a={};for(r in t)t.hasOwnProperty(r)&&(a[String(r).toLowerCase()]=t[r]);t=a}var s,n,w,b;return this instanceof z?(s=typeof i===l.STRING?i:t&&t[V]?t[V]:U&&U.userAgent?U.userAgent:d,n=new Bi(t,!0),w=e?((i,e)=>{var t,o={},r=e;if(!Si(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(t in i)o[t]=r[t]&&r[t].length%2==0?r[t].concat(i[t]):i[t];return o})(zi,e):zi,D.call(this,[[\"getBrowser\",(b=function(i){return i==v?function(){return new F(i,s,w,n).set(\"ua\",s).set(h,this.getBrowser()).set(u,this.getCPU()).set(m,this.getDevice()).set(f,this.getEngine()).set(g,this.getOS()).get()}:function(){return new F(i,s,w[i],n).parseUA().get()}})(h)],[\"getCPU\",b(u)],[\"getDevice\",b(m)],[\"getEngine\",b(f)],[\"getOS\",b(g)],[\"getResult\",b(v)],[\"getUA\",function(){return s}],[\"setUA\",function(i){return Ti(i)&&(s=_i(i,500)),this}]]).setUA(s),this):new z(i,e,t).getResult()}F.prototype.get=function(i){return i?this.data.hasOwnProperty(i)?this.data[i]:c:this.data},F.prototype.set=function(i,e){return this.data[i]=e,this},F.prototype.setCH=function(i){return this.uaCH=i,this},F.prototype.detectFeature=function(){if(U&&U.userAgent==this.ua)switch(this.itemType){case h:U.brave&&typeof U.brave.isBrave==l.FUNCTION&&this.set(k,\"Brave\");break;case m:!this.get(x)&&_&&_[S]&&this.set(x,S),\"Macintosh\"==this.get(E)&&U&&typeof U.standalone!==l.UNDEFINED&&U.maxTouchPoints&&2<U.maxTouchPoints&&this.set(E,\"iPad\").set(x,t);break;case g:!this.get(k)&&_&&_[I]&&this.set(k,_[I]);break;case v:var e=this.data,i=function(i){return e[i].getItem().detectFeature().get()};this.set(h,i(h)).set(u,i(u)).set(m,i(m)).set(f,i(f)).set(g,i(g))}return this},F.prototype.parseUA=function(){switch(this.itemType!=v&&H.call(this.data,this.ua,this.rgxMap),this.itemType){case h:this.set(j,B(this.get(C)));break;case g:var i;\"iOS\"==this.get(k)&&\"18.6\"==this.get(C)&&(i=/\\) Version\\/([\\d\\.]+)/.exec(this.ua))&&26<=parseInt(i[1].substring(0,2),10)&&this.set(C,i[1])}return this},F.prototype.parseCH=function(){var i,e=this.uaCH,t=this.rgxMap;switch(this.itemType){case h:case f:var o,r=e[$]||e[L];if(r)for(var a=0;a<r.length;a++){var s=r[a].brand||r[a],n=r[a].version;this.itemType==h&&!/not.a.brand/i.test(s)&&(!o||/Chrom/.test(o)&&s!=gi||o==vi&&/WebView2/.test(s))&&(s=p(s,Fi),(o=this.get(k))&&!/Chrom/.test(o)&&/Chrom/.test(s)||this.set(k,s).set(C,n).set(j,B(n)),o=s),this.itemType==f&&s==gi&&this.set(C,n)}break;case u:var w=e[N];w&&(\"64\"==e[J]&&(w+=\"64\"),H.call(this.data,w+\";\",t));break;case m:if(e[S]&&this.set(x,S),e[E]&&(this.set(E,e[E]),this.get(x)&&this.get(y)||(H.call(w={},\"droid 9; \"+e[E]+\")\",t),!this.get(x)&&w.type&&this.set(x,w.type),!this.get(y)&&w.vendor&&this.set(y,w.vendor))),e[T]){if(\"string\"!=typeof e[T])for(var b=0;!i&&b<e[T].length;)i=p(e[T][b++],Di);else i=p(e[T],Di);this.set(x,i)}break;case g:var d,w=e[I];w&&(d=e[W],w==Ci&&(d=13<=parseInt(B(d),10)?\"11\":\"10\"),this.set(k,w).set(C,d)),this.get(k)==Ci&&\"Xbox\"==e[E]&&this.set(k,\"Xbox\").set(C,c);break;case v:var l=this.data,w=function(i){return l[i].getItem().setCH(e).parseCH().get()};this.set(h,w(h)).set(u,w(u)).set(m,w(m)).set(f,w(f)).set(g,w(g))}return this},z.VERSION=\"2.0.9\",z.BROWSER=A([k,C,j,x]),z.CPU=A([N]),z.DEVICE=A([E,y,x,P,S,e,t,o,G]),z.ENGINE=z.OS=A([k,C]),typeof exports!==l.UNDEFINED?(exports=typeof module!==l.UNDEFINED&&module.exports?module.exports=z:exports).UAParser=z:typeof define===l.FUNCTION&&define.amd?define(function(){return z}):Ni&&(i.UAParser=z);var Hi,Mi=Ni&&(i.jQuery||i.Zepto);Mi&&!Mi.ua&&(Hi=new z,Mi.ua=Hi.getResult(),Mi.ua.get=function(){return Hi.getUA()},Mi.ua.set=function(i){Hi.setUA(i);var e,t=Hi.getResult();for(e in t)Mi.ua[e]=t[e]})})(\"object\"==typeof window?window:this);"
  },
  {
    "path": "dist/ua-parser.pack.mjs",
    "content": "/* UAParser.js v2.0.9\n   Copyright © 2012-2026 Faisal Salman <f@faisalman.com>\n   AGPLv3 License */\nfunction B(i){for(var e={},o=0;o<i.length;o++)e[i[o].toUpperCase()]=i[o];return e}function H(i){return Si(i)?z(/[^\\d\\.]/g,i).split(\".\")[0]:void 0}function A(i,e){if(i&&e)for(var o,t,r,a,s,n=0;n<e.length&&!a;){for(var w=e[n],d=e[n+1],b=o=0;b<w.length&&!a&&w[b];)if(a=w[b++].exec(i))for(t=0;t<d.length;t++)s=a[++o],typeof(r=d[t])===l.OBJECT&&0<r.length?2===r.length?typeof r[1]==l.FUNCTION?this[r[0]]=r[1].call(this,s):this[r[0]]=r[1]:3<=r.length&&(typeof r[1]!==l.FUNCTION||r[1].exec&&r[1].test?3==r.length?this[r[0]]=s?s.replace(r[1],r[2]):void 0:4==r.length?this[r[0]]=s?r[3].call(this,s.replace(r[1],r[2])):void 0:4<r.length&&(this[r[0]]=s?r[3].apply(this,[s.replace(r[1],r[2])].concat(r.slice(4))):void 0):3<r.length?this[r[0]]=s?r[1].apply(this,r.slice(2)):void 0:this[r[0]]=s?r[1].call(this,s,r[2]):void 0):this[r]=s||void 0;n+=2}}function c(i,e){for(var o in e)if(typeof e[o]===l.OBJECT&&0<e[o].length){for(var t=0;t<e[o].length;t++)if(Ni(e[o][t],i))return\"?\"===o?void 0:o}else if(Ni(e[o],i))return\"?\"===o?void 0:o;return e.hasOwnProperty(\"*\")?e[\"*\"]:i}function M(e,i){var o=Di.init[i],t=Di.isIgnore[i]||0,r=Di.isIgnoreRgx[i]||0,a=Di.toString[i]||0;function s(){U.call(this,o)}return s.prototype.getItem=function(){return e},s.prototype.withClientHints=function(){return _?_.getHighEntropyValues(ti).then(function(i){return e.setCH(new Fi(i,!1)).parseCH().get()}):e.parseCH().get()},s.prototype.withFeatureCheck=function(){return e.detectFeature().get()},i!=f&&(s.prototype.is=function(i){var e,o=!1;for(e in this)if(this.hasOwnProperty(e)&&!Ni(t,e)&&q(r?z(r,this[e]):this[e])==q(r?z(r,i):i)){if(o=!0,i!=l.UNDEFINED)break}else if(i==l.UNDEFINED&&o){o=!o;break}return o},s.prototype.toString=function(){var i,e=b;for(i in a)typeof this[a[i]]!==l.UNDEFINED&&(e+=(e?\" \":b)+this[a[i]]);return e||l.UNDEFINED}),s.prototype.then=function(i){function e(){for(var i in o)o.hasOwnProperty(i)&&(this[i]=o[i])}var o=this,t=(e.prototype={is:s.prototype.is,toString:s.prototype.toString,withClientHints:s.prototype.withClientHints,withFeatureCheck:s.prototype.withFeatureCheck},new e);return i(t),t},new s}var V=\"user-agent\",b=\"\",l={FUNCTION:\"function\",OBJECT:\"object\",STRING:\"string\",UNDEFINED:\"undefined\"},h=\"browser\",p=\"cpu\",u=\"device\",m=\"engine\",g=\"os\",f=\"result\",v=\"name\",k=\"type\",x=\"vendor\",y=\"version\",C=\"architecture\",P=\"major\",N=\"model\",j=\"console\",E=\"mobile\",o=\"tablet\",i=\"smarttv\",e=\"wearable\",R=\"xr\",G=\"embedded\",t=\"inapp\",L=\"brands\",S=\"formFactors\",$=\"fullVersionList\",T=\"platform\",W=\"platformVersion\",J=\"bitness\",r=\"sec-ch-ua\",X=r+\"-full-version-list\",Y=r+\"-arch\",Z=r+\"-\"+J,K=r+\"-form-factors\",Q=r+\"-\"+E,ii=r+\"-\"+N,ei=r+\"-\"+T,oi=ei+\"-version\",ti=[L,$,E,N,T,W,C,S,J],ri=\"Amazon\",a=\"Apple\",ai=\"ASUS\",si=\"BlackBerry\",s=\"Google\",ni=\"Huawei\",wi=\"Lenovo\",di=\"Honor\",bi=\"LG\",li=\"Microsoft\",ci=\"Motorola\",hi=\"OnePlus\",pi=\"OPPO\",ui=\"Samsung\",mi=\"Sony\",gi=\"Xiaomi\",fi=\"Zebra\",vi=\"Chromium\",n=\"Chromecast\",ki=\"Edge\",xi=\"Firefox\",w=\"Opera\",yi=\"Facebook\",d=\"Mobile \",O=\" Browser\",Ci=\"Windows\",I=typeof window!==l.UNDEFINED&&window.navigator?window.navigator:void 0,_=I&&I.userAgentData?I.userAgentData:void 0,Ni=function(i,e){if(typeof i===l.OBJECT&&0<i.length){for(var o in i)if(q(e)==q(i[o]))return!0;return!1}return!!Si(i)&&q(e)==q(i)},Ei=function(i,e){for(var o in i)return/^(browser|cpu|device|engine|os)$/.test(o)||!!e&&Ei(i[o])},Si=function(i){return typeof i===l.STRING},Ti=function(i){if(i){for(var e,o=[],t=z(/\\\\?\\\"/g,i).split(\",\"),r=0;r<t.length;r++)-1<t[r].indexOf(\";\")?(e=Ii(t[r]).split(\";v=\"),o[r]={brand:e[0],version:e[1]}):o[r]=Ii(t[r]);return o}},q=function(i){return Si(i)?i.toLowerCase():i},U=function(i){for(var e in i)i.hasOwnProperty(e)&&(typeof(e=i[e])==l.OBJECT&&2==e.length?this[e[0]]=e[1]:this[e]=void 0);return this},z=function(i,e){return Si(e)?e.replace(i,b):e},Oi=function(i){return z(/\\\\?\\\"/g,i)},Ii=function(i,e){return i=z(/^\\s\\s*/,String(i)),typeof e===l.UNDEFINED?i:i.substring(0,e)},_i={ME:\"4.90\",\"NT 3.51\":\"3.51\",\"NT 4.0\":\"4.0\",2e3:[\"5.0\",\"5.01\"],XP:[\"5.1\",\"5.2\"],Vista:\"6.0\",7:\"6.1\",8:\"6.2\",8.1:\"6.3\",10:[\"6.4\",\"10.0\"],NT:\"\"},qi={embedded:\"Automotive\",mobile:\"Mobile\",tablet:[\"Tablet\",\"EInk\"],smarttv:\"TV\",wearable:\"Watch\",xr:[\"VR\",\"XR\"],\"?\":[\"Desktop\",\"Unknown\"],\"*\":void 0},Ui={Chrome:\"Google Chrome\",Edge:\"Microsoft Edge\",\"Edge WebView2\":\"Microsoft Edge WebView2\",\"Chrome WebView\":\"Android WebView\",\"Chrome Headless\":\"HeadlessChrome\",\"Huawei Browser\":\"HuaweiBrowser\",\"MIUI Browser\":\"Miui Browser\",\"Opera Mobi\":\"OperaMobile\",Yandex:\"YaBrowser\"},zi={browser:[[/\\b(?:crmo|crios)\\/([\\w\\.]+)/i],[y,[v,d+\"Chrome\"]],[/webview.+edge\\/([\\w\\.]+)/i],[y,[v,ki+\" WebView\"]],[/edg(?:e|ios|a)?\\/([\\w\\.]+)/i],[y,[v,\"Edge\"]],[/(opera mini)\\/([-\\w\\.]+)/i,/(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i,/(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i],[v,y],[/opios[\\/ ]+([\\w\\.]+)/i],[y,[v,w+\" Mini\"]],[/\\bop(?:rg)?x\\/([\\w\\.]+)/i],[y,[v,w+\" GX\"]],[/\\bopr\\/([\\w\\.]+)/i],[y,[v,w]],[/\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i],[y,[v,\"Baidu\"]],[/\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i],[y,[v,\"Maxthon\"]],[/(kindle)\\/([\\w\\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i,/(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i,/(?:ms|\\()(ie) ([\\w\\.]+)/i,/(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\\/v?([-\\w\\.]+)/i,/(brave)(?: chrome)?\\/([\\d\\.]+)/i,/(aloha|heytap|ovi|115|surf|qwant)browser\\/([\\d\\.]+)/i,/(qwant)(?:ios|mobile)\\/([\\d\\.]+)/i,/(ecosia|weibo)(?:__| \\w+@)([\\d\\.]+)/i],[v,y],[/quark(?:pc)?\\/([-\\w\\.]+)/i],[y,[v,\"Quark\"]],[/\\bddg\\/([\\w\\.]+)/i],[y,[v,\"DuckDuckGo\"]],[/(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i],[y,[v,\"UCBrowser\"]],[/microm.+\\bqbcore\\/([\\w\\.]+)/i,/\\bqbcore\\/([\\w\\.]+).+microm/i,/micromessenger\\/([\\w\\.]+)/i],[y,[v,\"WeChat\"]],[/konqueror\\/([\\w\\.]+)/i],[y,[v,\"Konqueror\"]],[/trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i],[y,[v,\"IE\"]],[/ya(?:search)?browser\\/([\\w\\.]+)/i],[y,[v,\"Yandex\"]],[/slbrowser\\/([\\w\\.]+)/i],[y,[v,\"Smart \"+wi+O]],[/(av(?:ast|g|ira))\\/([\\w\\.]+)/i],[[v,/(.+)/,\"$1 Secure\"+O],y],[/norton\\/([\\w\\.]+)/i],[y,[v,\"Norton Private\"+O]],[/\\bfocus\\/([\\w\\.]+)/i],[y,[v,xi+\" Focus\"]],[/ mms\\/([\\w\\.]+)$/i],[y,[v,w+\" Neon\"]],[/ opt\\/([\\w\\.]+)$/i],[y,[v,w+\" Touch\"]],[/coc_coc\\w+\\/([\\w\\.]+)/i],[y,[v,\"Coc Coc\"]],[/dolfin\\/([\\w\\.]+)/i],[y,[v,\"Dolphin\"]],[/coast\\/([\\w\\.]+)/i],[y,[v,w+\" Coast\"]],[/miuibrowser\\/([\\w\\.]+)/i],[y,[v,\"MIUI\"+O]],[/fxios\\/([\\w\\.-]+)/i],[y,[v,d+xi]],[/\\bqihoobrowser\\/?([\\w\\.]*)/i],[y,[v,\"360\"]],[/\\b(qq)\\/([\\w\\.]+)/i],[[v,/(.+)/,\"$1Browser\"],y],[/(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i],[[v,/(.+)/,\"$1\"+O],y],[/samsungbrowser\\/([\\w\\.]+)/i],[y,[v,ui+\" Internet\"]],[/metasr[\\/ ]?([\\d\\.]+)/i],[y,[v,\"Sogou Explorer\"]],[/(sogou)mo\\w+\\/([\\d\\.]+)/i],[[v,\"Sogou Mobile\"],y],[/(electron)\\/([\\w\\.]+) safari/i,/(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i,/m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i],[v,y],[/(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i],[v],[/ome\\/([\\w\\.]+).+(iron(?= saf)|360(?=[es]e$))/i],[y,v],[/((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i],[[v,yi],y,[k,t]],[/(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i,/(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i,/(daum)apps[\\/ ]([\\w\\.]+)/i,/safari (line)\\/([\\w\\.]+)/i,/\\b(line)\\/([\\w\\.]+)\\/iab/i,/(alipay)client\\/([\\w\\.]+)/i,/(twitter)(?:and| f.+e\\/([\\w\\.]+))/i,/(bing)(?:web|sapphire)\\/([\\w\\.]+)/i,/(instagram|snapchat|klarna)[\\/ ]([-\\w\\.]+)/i],[v,y,[k,t]],[/\\bgsa\\/([\\w\\.]+) .*safari\\//i],[y,[v,\"GSA\"],[k,t]],[/(?:musical_ly|trill)(?:.+app_?version\\/|_)([\\w\\.]+)/i],[y,[v,\"TikTok\"],[k,t]],[/\\[(linkedin)app\\]/i],[v,[k,t]],[/(zalo(?:app)?)[\\/\\sa-z]*([\\w\\.-]+)/i],[[v,/(.+)/,\"Zalo\"],y,[k,t]],[/(chromium)[\\/ ]([-\\w\\.]+)/i],[v,y],[/ome-(lighthouse)$/i],[v,[k,\"fetcher\"]],[/headlesschrome(?:\\/([\\w\\.]+)| )/i],[y,[v,\"Chrome Headless\"]],[/wv\\).+chrome\\/([\\w\\.]+).+edgw\\//i],[y,[v,ki+\" WebView2\"]],[/ wv\\).+(chrome)\\/([\\w\\.]+)/i],[[v,\"Chrome WebView\"],y],[/droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i],[y,[v,\"Android\"+O]],[/chrome\\/([\\w\\.]+) mobile/i],[y,[v,d+\"Chrome\"]],[/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i],[v,y],[/version\\/([\\w\\.\\,]+) .*mobile(?:\\/\\w+ | ?)safari/i],[y,[v,d+\"Safari\"]],[/iphone .*mobile(?:\\/\\w+ | ?)safari/i],[[v,d+\"Safari\"]],[/version\\/([\\w\\.\\,]+) .*(safari)/i],[y,v],[/webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i],[v,[y,\"1\"]],[/(webkit|khtml)\\/([\\w\\.]+)/i],[v,y],[/(?:mobile|tablet);.*(firefox)\\/([\\w\\.-]+)/i],[[v,d+xi],y],[/(navigator|netscape\\d?)\\/([-\\w\\.]+)/i],[[v,\"Netscape\"],y],[/(wolvic|librewolf)\\/([\\w\\.]+)/i],[v,y],[/mobile vr; rv:([\\w\\.]+)\\).+firefox/i],[y,[v,xi+\" Reality\"]],[/ekiohf.+(flow)\\/([\\w\\.]+)/i,/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\\/([-\\w\\.]+)$/i,/(firefox)\\/([\\w\\.]+)/i,/(mozilla)\\/([\\w\\.]+(?= .+rv\\:.+gecko\\/\\d+)|[0-4][\\w\\.]+(?!.+compatible))/i,/(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,/\\b(links) \\(([\\w\\.]+)/i],[v,[y,/_/g,\".\"]],[/(cobalt)\\/([\\w\\.]+)/i],[v,[y,/[^\\d\\.]+./,b]]],cpu:[[/\\b((amd|x|x86[-_]?|wow|win)64)\\b/i],[[C,\"amd64\"]],[/(ia32(?=;))/i,/\\b((i[346]|x)86)(pc)?\\b/i],[[C,\"ia32\"]],[/\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i],[[C,\"arm64\"]],[/\\b(arm(v[67])?ht?n?[fl]p?)\\b/i],[[C,\"armhf\"]],[/( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i],[[C,\"arm\"]],[/ sun4\\w[;\\)]/i],[[C,\"sparc\"]],[/\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i,/((ppc|powerpc)(64)?)( mac|;|\\))/i,/(?:osf1|[freopnt]{3,4}bsd) (alpha)/i],[[C,/ower/,b,q]],[/mc680.0/i],[[C,\"68k\"]],[/winnt.+\\[axp/i],[[C,\"alpha\"]]],device:[[/\\b(sch-i[89]0\\d|shw-m380s|sm-[ptx]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus 10)/i],[N,[x,ui],[k,o]],[/\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,/samsung[- ]((?!sm-[lr]|browser)[-\\w]+)/i,/sec-(sgh\\w+)/i],[N,[x,ui],[k,E]],[/(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)[\\/\\);]/i],[N,[x,a],[k,E]],[/\\b(?:ios|apple\\w+)\\/.+[\\(\\/](ipad)/i,/\\b(ipad)[\\d,]*[;\\] ].+(mac |i(pad)?)os/i],[N,[x,a],[k,o]],[/(macintosh);/i],[N,[x,a]],[/\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i],[N,[x,\"Sharp\"],[k,E]],[/\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i],[N,[x,di],[k,o]],[/honor([-\\w ]+)[;\\)]/i],[N,[x,di],[k,E]],[/\\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\\w\\. ]*(?= bui|\\)))\\b(?!.+d\\/s)/i],[N,[x,ni],[k,o]],[/(?:huawei) ?([-\\w ]+)[;\\)]/i,/\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][\\dc][adnt]?)\\b(?!.+d\\/s)/i],[N,[x,ni],[k,E]],[/oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,/\\b(?:xiao)?((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i],[[N,/_/g,\" \"],[x,gi],[k,o]],[/\\b; (\\w+) build\\/hm\\1/i,/\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i,/oid[^\\)]+; (redmi[\\-_ ]?(?:note|k)?[\\w_ ]+|m?[12]\\d[01]\\d\\w{3,6}|poco[\\w ]+|(shark )?\\w{3}-[ah]0|qin ?[1-3](s\\+|ultra| pro)?)( bui|; wv|\\))/i,/\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\\d{0,2}\\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\\))/i,/ ([\\w ]+) miui\\/v?\\d/i],[[N,/_/g,\" \"],[x,gi],[k,E]],[/droid.+; (cph2[3-6]\\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\\d|p[g-l]\\w[1m]10)\\b/i,/(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i],[N,[x,hi],[k,E]],[/; (\\w+) bui.+ oppo/i,/\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i],[N,[x,pi],[k,E]],[/\\b(opd2(\\d{3}a?))(?: bui|\\))/i],[N,[x,c,{OnePlus:[\"203\",\"304\",\"403\",\"404\",\"413\",\"415\"],\"*\":pi}],[k,o]],[/(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\\w\\+ ]*)(?: bui|\\))/i],[N,[x,\"BLU\"],[k,E]],[/; vivo (\\w+)(?: bui|\\))/i,/\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i],[N,[x,\"Vivo\"],[k,E]],[/\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i],[N,[x,\"Realme\"],[k,E]],[/(ideatab[-\\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\\d{3,4}(?:f[cu]|xu|[av])|yt\\d?-[jx]?\\d+[lfmx])( bui|;|\\)|\\/)/i,/lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i],[N,[x,wi],[k,o]],[/lenovo[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i],[N,[x,wi],[k,E]],[/\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,/\\bmot(?:orola)?[- ]([\\w\\s]+)(\\)| bui)/i,/((?:moto(?! 360)[-\\w\\(\\) ]+|xt\\d{3,4}[cgkosw\\+]?[-\\d]*|nexus 6)(?= bui|\\)))/i],[N,[x,ci],[k,E]],[/\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i],[N,[x,ci],[k,o]],[/\\b(?:lg)?([vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i],[N,[x,bi],[k,o]],[/(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,/\\blg[-e;\\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\\w+)/i,/\\blg-?([\\d\\w]+) bui/i],[N,[x,bi],[k,E]],[/(nokia) (t[12][01])/i],[x,N,[k,o]],[/(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,/nokia[-_ ]?(([-\\w\\. ]*?))( bui|\\)|;|\\/)/i],[[N,/_/g,\" \"],[k,E],[x,\"Nokia\"]],[/(pixel (c|tablet))\\b/i],[N,[x,s],[k,o]],[/droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\\d ]*a?( pro)?( xl)?( fold)?( \\(5g\\))?)( bui|\\))/i],[N,[x,s],[k,E]],[/(google) (pixelbook( go)?)/i],[x,N],[/droid.+; (a?\\d[0-2]{2}so|[c-g]\\d{4}|so[-gl]\\w+|xq-\\w\\w\\d\\d)(?= bui|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i],[N,[x,mi],[k,E]],[/sony tablet [ps]/i,/\\b(?:sony)?sgp\\w+(?: bui|\\))/i],[[N,\"Xperia Tablet\"],[x,mi],[k,o]],[/(alexa)webm/i,/(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i,/(kf[a-z]+)( bui|\\)).+silk\\//i],[N,[x,ri],[k,o]],[/((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i],[[N,/(.+)/g,\"Fire Phone $1\"],[x,ri],[k,E]],[/(playbook);[-\\w\\),; ]+(rim)/i],[N,x,[k,o]],[/\\b((?:bb[a-f]|st[hv])100-\\d)/i,/(?:blackberry|\\(bb10;) (\\w+)/i],[N,[x,si],[k,E]],[/(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i],[N,[x,ai],[k,o]],[/ (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i],[N,[x,ai],[k,E]],[/(nexus 9)/i],[N,[x,\"HTC\"],[k,o]],[/(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i,/(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,/(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i],[x,[N,/_/g,\" \"],[k,E]],[/tcl (xess p17aa)/i,/droid [\\w\\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\\w(\\w|\\w\\w))?(\\)| bui)/i],[N,[x,\"TCL\"],[k,o]],[/droid [\\w\\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\\w(\\w|\\w\\w))?(\\)| bui)/i],[N,[x,\"TCL\"],[k,E]],[/(itel) ((\\w+))/i],[[x,q],N,[k,c,{tablet:[\"p10001l\",\"w7001\"],\"*\":\"mobile\"}]],[/droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i],[N,[x,\"Acer\"],[k,o]],[/droid.+; (m[1-5] note) bui/i,/\\bmz-([-\\w]{2,})/i],[N,[x,\"Meizu\"],[k,E]],[/; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i],[N,[x,\"Ulefone\"],[k,E]],[/; (energy ?\\w+)(?: bui|\\))/i,/; energizer ([\\w ]+)(?: bui|\\))/i],[N,[x,\"Energizer\"],[k,E]],[/; cat (b35);/i,/; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i],[N,[x,\"Cat\"],[k,E]],[/((?:new )?andromax[\\w- ]+)(?: bui|\\))/i],[N,[x,\"Smartfren\"],[k,E]],[/droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i],[N,[x,\"Nothing\"],[k,E]],[/; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,/archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i],[N,[x,\"Archos\"],[k,o]],[/archos ([\\w ]+)( b|\\))/i,/; (ac[3-6]\\d\\w{2,8})( b|\\))/i],[N,[x,\"Archos\"],[k,E]],[/; (n159v)/i],[N,[x,\"HMD\"],[k,E]],[/(imo) (tab \\w+)/i,/(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i],[x,N,[k,o]],[/(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,/; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\\w\\+ ]+?)(?: bui|\\)|; r)/i,/(hp) ([\\w ]+\\w)/i,/(microsoft); (lumia[\\w ]+)/i,/(oppo) ?([\\w ]+) bui/i,/(hisense) ([ehv][\\w ]+)\\)/i,/droid[^;]+; (philips)[_ ]([sv-x][\\d]{3,4}[xz]?)/i],[x,N,[k,E]],[/(kobo)\\s(ereader|touch)/i,/(hp).+(touchpad(?!.+tablet)|tablet)/i,/(kindle)\\/([\\w\\.]+)/i],[x,N,[k,o]],[/(surface duo)/i],[N,[x,li],[k,o]],[/droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i],[N,[x,\"Fairphone\"],[k,E]],[/((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i],[N,[x,\"Nvidia\"],[k,o]],[/(sprint) (\\w+)/i],[x,N,[k,E]],[/(kin\\.[onetw]{3})/i],[[N,/\\./g,\" \"],[x,li],[k,E]],[/droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i],[N,[x,fi],[k,o]],[/droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i],[N,[x,fi],[k,E]],[/(philips)[\\w ]+tv/i,/smart-tv.+(samsung)/i],[x,[k,i]],[/hbbtv.+maple;(\\d+)/i],[[N,/^/,\"SmartTV\"],[x,ui],[k,i]],[/(vizio)(?: |.+model\\/)(\\w+-\\w+)/i,/tcast.+(lg)e?. ([-\\w]+)/i],[x,N,[k,i]],[/(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i],[[x,bi],[k,i]],[/(apple) ?tv/i],[x,[N,a+\" TV\"],[k,i]],[/crkey.*devicetype\\/chromecast/i],[[N,n+\" Third Generation\"],[x,s],[k,i]],[/crkey.*devicetype\\/([^/]*)/i],[[N,/^/,\"Chromecast \"],[x,s],[k,i]],[/fuchsia.*crkey/i],[[N,n+\" Nest Hub\"],[x,s],[k,i]],[/crkey/i],[[N,n],[x,s],[k,i]],[/(portaltv)/i],[N,[x,yi],[k,i]],[/droid.+aft(\\w+)( bui|\\))/i],[N,[x,ri],[k,i]],[/(shield \\w+ tv)/i],[N,[x,\"Nvidia\"],[k,i]],[/\\(dtv[\\);].+(aquos)/i,/(aquos-tv[\\w ]+)\\)/i],[N,[x,\"Sharp\"],[k,i]],[/(bravia[\\w ]+)( bui|\\))/i],[N,[x,mi],[k,i]],[/(mi(tv|box)-?\\w+) bui/i],[N,[x,gi],[k,i]],[/Hbbtv.*(technisat) (.*);/i],[x,N,[k,i]],[/\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i,/hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i],[[x,/.+\\/(\\w+)/,\"$1\",c,{LG:\"lge\"}],[N,Ii],[k,i]],[/(playstation \\w+)/i],[N,[x,mi],[k,j]],[/\\b(xbox(?: one)?(?!; xbox))[\\); ]/i],[N,[x,li],[k,j]],[/(ouya)/i,/(nintendo) (\\w+)/i,/(retroid) (pocket ([^\\)]+))/i,/(valve).+(steam deck)/i,/droid.+; ((shield|rgcube|gr0006))( bui|\\))/i],[[x,c,{Nvidia:\"Shield\",Anbernic:\"RGCUBE\",Logitech:\"GR0006\"}],N,[k,j]],[/\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i],[N,[x,ui],[k,e]],[/((pebble))app/i,/(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i],[x,N,[k,e]],[/(ow(?:19|20)?we?[1-3]{1,3})/i],[N,[x,pi],[k,e]],[/(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i],[N,[x,a],[k,e]],[/(opwwe\\d{3})/i],[N,[x,hi],[k,e]],[/(moto 360)/i],[N,[x,ci],[k,e]],[/(smartwatch 3)/i],[N,[x,mi],[k,e]],[/(g watch r)/i],[N,[x,bi],[k,e]],[/droid.+; (wt63?0{2,3})\\)/i],[N,[x,fi],[k,e]],[/droid.+; (glass) \\d/i],[N,[x,s],[k,R]],[/(pico) ([\\w ]+) os\\d/i],[x,N,[k,R]],[/(quest( \\d| pro)?s?).+vr/i],[N,[x,yi],[k,R]],[/mobile vr; rv.+firefox/i],[[k,R]],[/(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i],[x,[k,G]],[/(aeobc)\\b/i],[N,[x,ri],[k,G]],[/(homepod).+mac os/i],[N,[x,a],[k,G]],[/windows iot/i],[[k,G]],[/droid.+; ([\\w- ]+) (4k|android|smart|google)[- ]?tv/i],[N,[k,i]],[/\\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\\w ]+safari)\\b/i],[[k,i]],[/droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew|; hmsc).+?(mobile|vr|\\d) safari/i],[N,[k,c,{mobile:\"Mobile\",xr:\"VR\",\"*\":o}]],[/\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i],[[k,o]],[/(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i],[[k,E]],[/droid .+?; ([\\w\\. -]+)( bui|\\))/i],[N,[x,\"Generic\"]]],engine:[[/windows.+ edge\\/([\\w\\.]+)/i],[y,[v,ki+\"HTML\"]],[/(arkweb)\\/([\\w\\.]+)/i],[v,y],[/webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i],[y,[v,\"Blink\"]],[/(presto)\\/([\\w\\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i,/ekioh(flow)\\/([\\w\\.]+)/i,/(khtml|tasman|links|dillo)[\\/ ]\\(?([\\w\\.]+)/i,/(icab)[\\/ ]([23]\\.[\\d\\.]+)/i,/\\b(libweb)/i],[v,y],[/ladybird\\//i],[[v,\"LibWeb\"]],[/rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i],[y,v]],os:[[/(windows nt) (6\\.[23]); arm/i],[[v,/N/,\"R\"],[y,c,_i]],[/(windows (?:phone|mobile|iot))(?: os)?[\\/ ]?([\\d\\.]*( se)?)/i,/(windows)[\\/ ](1[01]|2000|3\\.1|7|8(\\.1)?|9[58]|me|server 20\\d\\d( r2)?|vista|xp)/i],[v,y],[/windows nt ?([\\d\\.\\)]*)(?!.+xbox)/i,/\\bwin(?=3| ?9|n)(?:nt| 9x )?([\\d\\.;]*)/i],[[y,/(;|\\))/g,\"\",c,_i],[v,Ci]],[/(windows ce)\\/?([\\d\\.]*)/i],[v,y],[/[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i,/(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\\/ ]([\\w\\.]+)/i,/\\btvos ?([\\w\\.]+)/i,/cfnetwork\\/.+darwin/i],[[y,/_/g,\".\"],[v,\"iOS\"]],[/(mac os x) ?([\\w\\. ]*)/i,/(macintosh|mac_powerpc\\b)(?!.+(haiku|morphos))/i],[[v,\"macOS\"],[y,/_/g,\".\"]],[/android ([\\d\\.]+).*crkey/i],[y,[v,n+\" Android\"]],[/fuchsia.*crkey\\/([\\d\\.]+)/i],[y,[v,n+\" Fuchsia\"]],[/crkey\\/([\\d\\.]+).*devicetype\\/smartspeaker/i],[y,[v,n+\" SmartSpeaker\"]],[/linux.*crkey\\/([\\d\\.]+)/i],[y,[v,n+\" Linux\"]],[/crkey\\/([\\d\\.]+)/i],[y,[v,n]],[/droid ([\\w\\.]+)\\b.+(android[- ]x86)/i],[y,v],[/(ubuntu) ([\\w\\.]+) like android/i],[[v,/(.+)/,\"$1 Touch\"],y],[/(harmonyos)[\\/ ]?([\\d\\.]*)/i,/(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\\w*[-\\/\\.; ]?([\\d\\.]*)/i],[v,y],[/\\(bb(10);/i],[y,[v,si]],[/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i],[y,[v,\"Symbian\"]],[/mozilla\\/[\\d\\.]+ \\((?:mobile[;\\w ]*|tablet|tv|[^\\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\\w\\.]+)\\).+gecko\\//i],[y,[v,xi+\" OS\"]],[/\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i,/webos(?:[ \\/]?|\\.tv-20(?=2[2-9]))(\\d[\\d\\.]*)/i],[y,[v,\"webOS\"]],[/web0s;.+?(?:chr[o0]me|safari)\\/(\\d+)/i],[[y,c,{25:\"120\",24:\"108\",23:\"94\",22:\"87\",6:\"79\",5:\"68\",4:\"53\",3:\"38\",2:\"538\",1:\"537\",\"*\":\"TV\"}],[v,\"webOS\"]],[/watch(?: ?os[,\\/ ]|\\d,\\d\\/)([\\d\\.]+)/i],[y,[v,\"watchOS\"]],[/cros [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i],[y,[v,\"Chrome OS\"]],[/kepler ([\\w\\.]+); (aft|aeo)/i],[y,[v,\"Vega OS\"]],[/(netrange)mmh/i,/(nettv)\\/(\\d+\\.[\\w\\.]+)/i,/(nintendo|playstation) (\\w+)/i,/(xbox); +xbox ([^\\);]+)/i,/(pico) .+os([\\w\\.]+)/i,/\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i,/linux.+(mint)[\\/\\(\\) ]?([\\w\\.]*)/i,/(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\\d\\.]*)/i,/([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\\/ ]?(?!chrom|package)([-\\w\\.]*)/i,/((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i,/\\b(aix)[; ]([1-9\\.]{0,4})/i,/(hurd|linux|morphos)(?: (?:arm|x86|ppc)\\w*| ?)([\\w\\.]*)/i,/(gnu) ?([\\w\\.]*)/i,/\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i,/(haiku) ?(r\\d)?/i],[v,y],[/(sunos) ?([\\d\\.]*)/i],[[v,\"Solaris\"],y],[/\\b(beos|os\\/2|amigaos|openvms|hp-ux|serenityos)/i,/(unix) ?([\\w\\.]*)/i],[v,y]]},Di=(w={init:{},isIgnore:{},isIgnoreRgx:{},toString:{}},U.call(w.init,[[h,[v,y,P,k]],[p,[C]],[u,[k,N,x]],[m,[v,y]],[g,[v,y]]]),U.call(w.isIgnore,[[h,[y,P]],[m,[y]],[g,[y]]]),U.call(w.isIgnoreRgx,[[h,/ ?browser$/i],[g,/ ?os$/i]]),U.call(w.toString,[[h,[v,y]],[p,[C]],[u,[x,N]],[m,[v,y]],[g,[v,y]]]),w);function Fi(i,e){if(i=i||{},U.call(this,ti),e)U.call(this,[[L,Ti(i[r])],[$,Ti(i[X])],[E,/\\?1/.test(i[Q])],[N,Oi(i[ii])],[T,Oi(i[ei])],[W,Oi(i[oi])],[C,Oi(i[Y])],[S,Ti(i[K])],[J,Oi(i[Z])]]);else for(var o in i)this.hasOwnProperty(o)&&typeof i[o]!==l.UNDEFINED&&(this[o]=i[o])}function D(i,e,o,t){return U.call(this,[[\"itemType\",i],[\"ua\",e],[\"uaCH\",t],[\"rgxMap\",o],[\"data\",M(this,i)]]),this}function F(i,e,o){if(typeof i===l.OBJECT?(e=Ei(i,!0)?(typeof e===l.OBJECT&&(o=e),i):void(o=i),i=void 0):typeof i!==l.STRING||Ei(e,!0)||(o=e,e=void 0),o)if(typeof o.append===l.FUNCTION){var t={};o.forEach(function(i,e){t[String(e).toLowerCase()]=i}),o=t}else{var r,a={};for(r in o)o.hasOwnProperty(r)&&(a[String(r).toLowerCase()]=o[r]);o=a}var s,n,w,d;return this instanceof F?(s=typeof i===l.STRING?i:o&&o[V]?o[V]:I&&I.userAgent?I.userAgent:b,n=new Fi(o,!0),w=e?((i,e)=>{var o,t={},r=e;if(!Ei(e))for(var a in r={},e)for(var s in e[a])r[s]=e[a][s].concat(r[s]||[]);for(o in i)t[o]=r[o]&&r[o].length%2==0?r[o].concat(i[o]):i[o];return t})(zi,e):zi,U.call(this,[[\"getBrowser\",(d=function(i){return i==f?function(){return new D(i,s,w,n).set(\"ua\",s).set(h,this.getBrowser()).set(p,this.getCPU()).set(u,this.getDevice()).set(m,this.getEngine()).set(g,this.getOS()).get()}:function(){return new D(i,s,w[i],n).parseUA().get()}})(h)],[\"getCPU\",d(p)],[\"getDevice\",d(u)],[\"getEngine\",d(m)],[\"getOS\",d(g)],[\"getResult\",d(f)],[\"getUA\",function(){return s}],[\"setUA\",function(i){return Si(i)&&(s=Ii(i,500)),this}]]).setUA(s),this):new F(i,e,o).getResult()}D.prototype.get=function(i){return i?this.data.hasOwnProperty(i)?this.data[i]:void 0:this.data},D.prototype.set=function(i,e){return this.data[i]=e,this},D.prototype.setCH=function(i){return this.uaCH=i,this},D.prototype.detectFeature=function(){if(I&&I.userAgent==this.ua)switch(this.itemType){case h:I.brave&&typeof I.brave.isBrave==l.FUNCTION&&this.set(v,\"Brave\");break;case u:!this.get(k)&&_&&_[E]&&this.set(k,E),\"Macintosh\"==this.get(N)&&I&&typeof I.standalone!==l.UNDEFINED&&I.maxTouchPoints&&2<I.maxTouchPoints&&this.set(N,\"iPad\").set(k,o);break;case g:!this.get(v)&&_&&_[T]&&this.set(v,_[T]);break;case f:var e=this.data,i=function(i){return e[i].getItem().detectFeature().get()};this.set(h,i(h)).set(p,i(p)).set(u,i(u)).set(m,i(m)).set(g,i(g))}return this},D.prototype.parseUA=function(){switch(this.itemType!=f&&A.call(this.data,this.ua,this.rgxMap),this.itemType){case h:this.set(P,H(this.get(y)));break;case g:var i;\"iOS\"==this.get(v)&&\"18.6\"==this.get(y)&&(i=/\\) Version\\/([\\d\\.]+)/.exec(this.ua))&&26<=parseInt(i[1].substring(0,2),10)&&this.set(y,i[1])}return this},D.prototype.parseCH=function(){var i,e=this.uaCH,o=this.rgxMap;switch(this.itemType){case h:case m:var t,r=e[$]||e[L];if(r)for(var a=0;a<r.length;a++){var s=r[a].brand||r[a],n=r[a].version;this.itemType==h&&!/not.a.brand/i.test(s)&&(!t||/Chrom/.test(t)&&s!=vi||t==ki&&/WebView2/.test(s))&&(s=c(s,Ui),(t=this.get(v))&&!/Chrom/.test(t)&&/Chrom/.test(s)||this.set(v,s).set(y,n).set(P,H(n)),t=s),this.itemType==m&&s==vi&&this.set(y,n)}break;case p:var w=e[C];w&&(\"64\"==e[J]&&(w+=\"64\"),A.call(this.data,w+\";\",o));break;case u:if(e[E]&&this.set(k,E),e[N]&&(this.set(N,e[N]),this.get(k)&&this.get(x)||(A.call(w={},\"droid 9; \"+e[N]+\")\",o),!this.get(k)&&w.type&&this.set(k,w.type),!this.get(x)&&w.vendor&&this.set(x,w.vendor))),e[S]){if(\"string\"!=typeof e[S])for(var d=0;!i&&d<e[S].length;)i=c(e[S][d++],qi);else i=c(e[S],qi);this.set(k,i)}break;case g:var b,w=e[T];w&&(b=e[W],w==Ci&&(b=13<=parseInt(H(b),10)?\"11\":\"10\"),this.set(v,w).set(y,b)),this.get(v)==Ci&&\"Xbox\"==e[N]&&this.set(v,\"Xbox\").set(y,void 0);break;case f:var l=this.data,w=function(i){return l[i].getItem().setCH(e).parseCH().get()};this.set(h,w(h)).set(p,w(p)).set(u,w(u)).set(m,w(m)).set(g,w(g))}return this},F.VERSION=\"2.0.9\",F.BROWSER=B([v,y,P,k]),F.CPU=B([C]),F.DEVICE=B([N,x,k,j,E,i,o,e,G]),F.ENGINE=F.OS=B([v,y]);export{F as UAParser};"
  },
  {
    "path": "package.json",
    "content": "{\n  \"title\": \"UAParser.js\",\n  \"name\": \"ua-parser-js\",\n  \"version\": \"2.0.9\",\n  \"author\": \"Faisal Salman <f@faisalman.com> (http://faisalman.com)\",\n  \"description\": \"Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment\",\n  \"keywords\": [\n    \"user-agent\",\n    \"client-hints\",\n    \"browser\",\n    \"engine\",\n    \"os\",\n    \"device\",\n    \"cpu\",\n    \"ua-parser-js\",\n    \"browser-detection\",\n    \"device-detection\",\n    \"os-detection\",\n    \"bot-detection\",\n    \"ai-detection\",\n    \"app-detection\",\n    \"crawler-detection\"\n  ],\n  \"homepage\": \"https://uaparser.dev\",\n  \"contributors\": [\n    \"Aamir Poonawalla <aamir@urx.com>\",\n    \"Admas <mollases@users.noreply.github.com>\",\n    \"Aiyush <aiyushdhar85@gmail.com>\",\n    \"algenon <m@antonz.ru>\",\n    \"Alvin Portillo <alvin@8thwall.com>\",\n    \"Amumu <yoyo837@hotmail.com>\",\n    \"Andreas Kogler <andreas.kogler@bitmovin.com>\",\n    \"Andrea Vaghi <andrea.vaghi@jobrapido.com>\",\n    \"Anton Zhiyanov <m@antonz.ru>\",\n    \"Arturo Mejia <amejia@blim.com>\",\n    \"Arun Rama Reddy <arunramareddy@gmail.com>\",\n    \"Austin Pray <austin@austinpray.com>\",\n    \"Beat YT <66485277+Beat-YT@users.noreply.github.com>\",\n    \"Bendeguz <symunona@gmail.com>\",\n    \"Benjamin Bertrand <bertrand.design@gmail.com>\",\n    \"Benjamin Urban <benjamin.urban@sueddeutsche.de>\",\n    \"boneyao <admin@boneyao.com>\",\n    \"Carl C Von Lewin <carlchristianlewin@gmail.com>\",\n    \"CESAR RAMOS <c@imagenproactiva.com>\",\n    \"Chad Killingsworth <ckillingsworth@jackhenry.com>\",\n    \"chenhui9279 <chenhui9279@autohome.com.cn>\",\n    \"chenyuan-new <53860479+chenyuan-new@users.noreply.github.com>\",\n    \"Christopher De Cairos <chris.decairos@gmail.com>\",\n    \"Cyrille David <cyrille@qonto.eu>\",\n    \"Dai Jie <daijie@php.net>\",\n    \"Danila Rodichkin <daniluk4000@outlook.com>\",\n    \"Dante <duanjl.china@gmail.com>\",\n    \"Dario Vladovic <d.vladimyr@gmail.com>\",\n    \"David Annez <david.annez@gmail.com>\",\n    \"Davit Barbakadze <jayarjo@gmail.com>\",\n    \"ddivernois <david-emmanuel.divernois@amadeus.com>\",\n    \"Deliaz <D3liaz@gmail.com>\",\n    \"Demis Palma <demis.palma@gmail.com>\",\n    \"dhoko <aurelien@protonmail.com>\",\n    \"dianhe <dianhe@webank.com>\",\n    \"dineshks1 <dineshks1@d.kumar44@outlook.com>\",\n    \"Dmitry Tyschenko <dtyschenko@gmail.com>\",\n    \"Douglas Li <doug@knotch.it>\",\n    \"Dumitru Uzun <contact@duzun.me>\",\n    \"Dustin <duburns@fanatics.com>\",\n    \"Elchin Valiyev <elchin.valiyev@autodesk.com>\",\n    \"Emil Hesslow <hesslow@gmail.com>\",\n    \"Eric Redon <eric.redon@coox.org>\",\n    \"Eric Schrenker <eric.schrenker@gmail.com>\",\n    \"Erik Hesselink <hesselink@gmail.com>\",\n    \"Fabian Becker <halfdan@xnorfz.de>\",\n    \"Faisal Salman <f@faisalman.com>\",\n    \"Frédéric Camblor <fcamblor@gmail.com>\",\n    \"Frederik Ring <frederik.ring@gmail.com>\",\n    \"Garrit Franke <garrit@slashdev.space>\",\n    \"Gerald Host <me@jacobford.co.uk>\",\n    \"Germán M. Bravo <german.mb@gmail.com>\",\n    \"Grigory Dmitrenko <grigory@snsk.ru>\",\n    \"gulpin <gulping.gulpin@gmail.com>\",\n    \"Hans Ott <hansott@hotmail.be>\",\n    \"Harald Reingruber <74898239+haraldreingruber-dedalus@users.noreply.github.com>\",\n    \"Hendrik Helwich <h.helwich@iplabs.de>\",\n    \"Hermann Ebert <ebbmo@HE.local>\",\n    \"hr6r <hedian@gmail.com>\",\n    \"Hyewon Kang <gpffps369@gmail.com>\",\n    \"Hyunbin <47051820+hyunbinseo@users.noreply.github.com>\",\n    \"Igor Topal <i.topal@smartweb.com.ua>\",\n    \"Ildar Kamalov <i.kamalov@adguard.com>\",\n    \"Ilya Daraseliya <idarase@gmail.com>\",\n    \"insanehong <insane.hong@navercorp.com>\",\n    \"jackpoll <jackpoll123456@gmail.com>\",\n    \"Jacky Choo <jackychoo@adly-macbook.local>\",\n    \"Jake Mc <startswithaj@users.noreply.github.com>\",\n    \"JBYoshi <12983479+JBYoshi@users.noreply.github.com>\",\n    \"Joey Parrish <joeyparrish@google.com>\",\n    \"John Tantalo <john.tantalo@gmail.com>\",\n    \"John Yanarella <jmy@codecatalyst.com>\",\n    \"Jon Buckley <jon@jbuckley.ca>\",\n    \"Josh Goldberg <joshuakgoldberg@outlook.com>\",\n    \"Junki-Ishida <junki_ishida@dwango.co.jp>\",\n    \"Kendall Buchanan <kendall@kendagriff.com>\",\n    \"KnifeLemon <role___play@naver.com>\",\n    \"kNoAPP <alldoneb@gmail.com>\",\n    \"Lee Treveil <leetreveil@gmail.com>\",\n    \"leonardo <leofiore@libero.it>\",\n    \"Levente Balogh <balogh.levente.hu@gmail.com>\",\n    \"Liam Quinn <lquinn@blackberry.com>\",\n    \"Lithin <lithin@webklipper.com>\",\n    \"liujunlve <liujunlve@henhaoji.com>\",\n    \"lj0812 <xoyljlj@163.com>\",\n    \"ll-syber <670159357@qq.com>\",\n    \"Loris Guignard <loris.guignard@gmail.com>\",\n    \"Lukas Drgon <lukas.drgon@gmail.com>\",\n    \"Lukas Eipert <leipert@users.noreply.github.com>\",\n    \"Malash <i@malash.me>\",\n    \"Martynas <martynas@firmfirm.co>\",\n    \"Masahiko Sato <masasato@yahoo-corp.jp>\",\n    \"Matt Brophy <matt@brophy.org>\",\n    \"Matthew Origer <karatecowboy@gmail.com>\",\n    \"Maximilian Haupt <mail@maximilianhaupt.com>\",\n    \"Max Maurer <maxemanuel.maurer@gmail.com>\",\n    \"Max Nordlund <max.nordlund@gmail.com>\",\n    \"Michael Hess <mhess@connectify.me>\",\n    \"Mike <mikehuebner@me.com>\",\n    \"MimyyK <michele.marais@hakisa.com>\",\n    \"Mok <mok@moekm.com>\",\n    \"nabetama <mao.nabeta@gmail.com>\",\n    \"naoh <naoh.cs03g@nctu.edu.tw>\",\n    \"Nicholas Ionata <nionata@ufl.edu>\",\n    \"Nikhil Motiani <nikhil.motiani@outlook.com>\",\n    \"Nik Rolls <nik@rolls.cc>\",\n    \"nionata <n.ionata129@gmail.com>\",\n    \"niris <nirisix@gmail.com>\",\n    \"Nobuo Okada <nookada@yahoo-corp.jp>\",\n    \"o.drapeza <o.drapeza@tinkoff.ru>\",\n    \"Oscar Becerra <oscarbecerra@google.com>\",\n    \"otakuSiD <otakusid@gmail.com>\",\n    \"Pablo Osés <opablo@gmail.com>\",\n    \"Paris Morgan <paris@8thwall.com>\",\n    \"patrick-nurt <github@pereira.dk>\",\n    \"Pavel Studeny <studeny@avast.com>\",\n    \"Peter Dave Hello <PeterDaveHello@users.noreply.github.com>\",\n    \"philippsimon <github@philippsimon.de>\",\n    \"Pieter Hendrickx <pieter.hendrickx@belfius.be>\",\n    \"Piper Chester <piperchester@gmail.com>\",\n    \"Queen Vinyl Darkscratch <vinyldarkscratch@gmail.com>\",\n    \"Raine Makelainen <raine.makelainen@jolla.com>\",\n    \"Raman Savaryn <homeneartheocean@gmail.com>\",\n    \"Riley Shaw <rileyjshaw@users.noreply.github.com>\",\n    \"Robert Tod <robert@qubit.com>\",\n    \"roman.savarin <roman.savarin@skywindgroup.com>\",\n    \"Ron Korland <ron@testim.io>\",\n    \"Ross Noble <rosshnoble@gmail.com>\",\n    \"ruicong <466403866@qq.com>\",\n    \"Runar Heggset <rukki093@gmail.com>\",\n    \"Ryohei Shima <shima01dev@gmail.com>\",\n    \"Sandro Sonntag <sandro.sonntag@adorsys.de>\",\n    \"sgautrea <shanegautreau@gmail.com>\",\n    \"shaharmor <shahar@peer5.com>\",\n    \"Shane Gautreau <sgautrea@opentext.com>\",\n    \"Shane Thacker <shane@steadymade.com>\",\n    \"Shreedhar <shreedhar@uber.com>\",\n    \"Simon Eisenmann <simon@longsleep.org>\",\n    \"Simon Lang <me@simonlang.org>\",\n    \"Stiekel <histkc@gmail.com>\",\n    \"sunny-mwx <30586210+sunny-mwx@users.noreply.github.com>\",\n    \"sUP <dani3l@gmail.com>\",\n    \"Sylvain Gizard <sylvain.gizard@gmail.com>\",\n    \"szchenghuang <szchenghuang@gmail.com>\",\n    \"Tanguy Krotoff <tkrotoff@gmail.com>\",\n    \"Tony Tomarchio <tony@tomarchio.cc>\",\n    \"Ulrich Schmidt <u.schmidt@velian.de>\",\n    \"Vadim Kurachevsky <vadim@hmvs.org>\",\n    \"Varun Sharma <varunsh@stepsecurity.io>\",\n    \"XhmikosR <xhmikosr@gmail.com>\",\n    \"Yılmaz <yilmazdemir36@gmail.com>\",\n    \"yuanyang <work_yuanyang@163.com>\",\n    \"Yun Young-jin <yupmin@yupmin-office-macmini.local>\",\n    \"Zach Bjornson <zbbjornson@gmail.com>\",\n    \"Ziding Zhang <zidingz@gmail.com>\"\n  ],\n  \"type\": \"commonjs\",\n  \"types\": \"src/main/ua-parser.d.ts\",\n  \"main\": \"src/main/ua-parser.js\",\n  \"module\": \"src/main/ua-parser.mjs\",\n  \"browser\": \"dist/ua-parser.pack.js\",\n  \"exports\": {\n    \".\": {\n      \"require\": \"./src/main/ua-parser.js\",\n      \"import\": \"./src/main/ua-parser.mjs\",\n      \"types\": \"./src/main/ua-parser.d.ts\"\n    },\n    \"./bot-detection\": {\n      \"require\": \"./src/bot-detection/bot-detection.js\",\n      \"import\": \"./src/bot-detection/bot-detection.mjs\",\n      \"types\": \"./src/bot-detection/bot-detection.d.ts\"\n    },\n    \"./browser-detection\": {\n      \"require\": \"./src/browser-detection/browser-detection.js\",\n      \"import\": \"./src/browser-detection/browser-detection.mjs\",\n      \"types\": \"./src/browser-detection/browser-detection.d.ts\"\n    },\n    \"./device-detection\": {\n      \"require\": \"./src/device-detection/device-detection.js\",\n      \"import\": \"./src/device-detection/device-detection.mjs\",\n      \"types\": \"./src/device-detection/device-detection.d.ts\"\n    },\n    \"./enums\": {\n      \"require\": \"./src/enums/ua-parser-enums.js\",\n      \"import\": \"./src/enums/ua-parser-enums.mjs\",\n      \"types\": \"./src/enums/ua-parser-enums.d.ts\"\n    },\n    \"./extensions\": {\n      \"require\": \"./src/extensions/ua-parser-extensions.js\",\n      \"import\": \"./src/extensions/ua-parser-extensions.mjs\",\n      \"types\": \"./src/extensions/ua-parser-extensions.d.ts\"\n    },\n    \"./helpers\": {\n      \"require\": \"./src/helpers/ua-parser-helpers.js\",\n      \"import\": \"./src/helpers/ua-parser-helpers.mjs\",\n      \"types\": \"./src/helpers/ua-parser-helpers.d.ts\"\n    }\n  },\n  \"files\": [\n    \"dist/*.?(m)js\",\n    \"dist/icons\",\n    \"src\"\n  ],\n  \"bin\": \"./script/cli.js\",\n  \"scripts\": {\n    \"build\": \"./script/build-dist.sh && ./script/build-esm.js\",\n    \"build+test\": \"npm run build && npm run test\",\n    \"fuzz\": \"jazzer ./test/fuzz/redos.js --sync\",\n    \"test\": \"./script/test-all.sh\",\n    \"test:dts-lint\": \"tsd --typings src/main/ua-parser.d.ts --files test/static/dts-lint.ts\",\n    \"test:eslint\": \"eslint --no-config-lookup src\",\n    \"test:jshint\": \"jshint src/main\",\n    \"test:lockfile-lint\": \"lockfile-lint -p package-lock.json\",\n    \"test:mocha\": \"mocha --recursive test/unit\",\n    \"test:playwright\": \"npx playwright install && playwright test test/e2e --browser all\"\n  },\n  \"dependencies\": {\n    \"detect-europe-js\": \"^0.1.2\",\n    \"is-standalone-pwa\": \"^0.1.1\",\n    \"ua-is-frozen\": \"^0.1.2\"\n  },\n  \"devDependencies\": {\n    \"@babel/parser\": \"7.15.8\",\n    \"@babel/traverse\": \"7.23.2\",\n    \"@playwright/test\": \"^1.57.0\",\n    \"eslint\": \"^9.39.1\",\n    \"jshint\": \"~2.13.6\",\n    \"lockfile-lint\": \"^4.14.1\",\n    \"mocha\": \"~8.2.0\",\n    \"requirejs\": \"2.3.2\",\n    \"safe-regex\": \"^2.1.1\",\n    \"tsd\": \"^0.29.0\",\n    \"uglify-js\": \"~3.19.3\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/faisalman/ua-parser-js.git\"\n  },\n  \"license\": \"AGPL-3.0-or-later\",\n  \"engines\": {\n    \"node\": \"*\"\n  },\n  \"directories\": {\n    \"dist\": \"dist\",\n    \"script\": \"script\",\n    \"src\": \"src\",\n    \"test\": \"test\"\n  },\n  \"bugs\": \"https://github.com/faisalman/ua-parser-js/issues\",\n  \"demo\": \"https://uaparser.dev\",\n  \"download\": \"https://raw.github.com/faisalman/ua-parser-js/master/dist/ua-parser.pack.js\",\n  \"funding\": [\n    {\n      \"type\": \"opencollective\",\n      \"url\": \"https://opencollective.com/ua-parser-js\"\n    },\n    {\n      \"type\": \"paypal\",\n      \"url\": \"https://paypal.me/faisalman\"\n    },\n    {\n      \"type\": \"github\",\n      \"url\": \"https://github.com/sponsors/faisalman\"\n    }\n  ]\n}\n"
  },
  {
    "path": "script/build-dist.sh",
    "content": "#!/usr/bin/env bash\n\nSRC_PATH=\"src/main/ua-parser.js\"\nMIN_PATH=\"dist/ua-parser.min.js\"\nPACK_PATH=\"dist/ua-parser.pack.js\"\n\nSRC_PATH_MJS=\"src/main/ua-parser.mjs\"\nMIN_PATH_MJS=\"dist/ua-parser.min.mjs\"\nPACK_PATH_MJS=\"dist/ua-parser.pack.mjs\"\n\n# minified\necho \"Generate ${MIN_PATH}\"\nuglifyjs $SRC_PATH -o $MIN_PATH --comments \"/^ UA/\"\n\necho \"Generate ${MIN_PATH_MJS}\"\nuglifyjs $SRC_PATH_MJS -o $MIN_PATH_MJS --comments \"/^ UA/\" --module\n\n# packed\necho \"Generate ${PACK_PATH}\"\nuglifyjs $SRC_PATH -o $PACK_PATH --comments \"/^ UA/\" --compress --mangle\n\necho \"Generate ${PACK_PATH_MJS}\"\nuglifyjs $SRC_PATH_MJS -o $PACK_PATH_MJS --comments \"/^ UA/\" --compress --mangle --module"
  },
  {
    "path": "script/build-esm.js",
    "content": "#!/usr/bin/env node\n/* jshint esversion: 6 */ \nconst fs = require('fs');\n\nconst defaultReplacements = {\n    mjs: [\n        [/(?<=const.+)(:)(?=.+require)/ig, ' as'],\n        [/const (.+?)\\s*=\\s*require\\(\\'\\.(.+)\\'\\)/ig, 'import $1 from \\'\\.$2.mjs\\''],\n        [/const (.+?)\\s*=\\s*require\\(\\'(.+)\\'\\)/ig, 'import $1 from \\'$2\\''],\n        [/module\\.exports =/ig, 'export']\n    ]\n}\n\nconst generateFile = (module) => {\n    let { src, dest, title, replacements } = module;\n    let text = fs.readFileSync(src, 'utf-8');\n\n    replacements.forEach(rep => {\n        text = text.replace(rep[0], rep[1]);\n    });\n\n    console.log(`Generate ${dest}`);\n\n    fs.writeFileSync(dest,\n`// ${title}\n// DO NOT EDIT THIS FILE!\n// Source: /${src}\n\n${text}`, 'utf-8');\n};\n\nconst files = [\n    {\n        src : 'src/main/ua-parser.js',\n        dest : 'src/main/ua-parser.mjs',\n        title : 'Generated ESM version of ua-parser-js',\n        replacements : [\n            [/\\(func[\\s\\S]+strict\\';/ig, ''],\n            [/esversion\\: 3/ig, 'esversion: 6'],\n            [/\\/[\\/\\s]+export[\\s\\S]+/ig,'export {UAParser};'],\n            ...defaultReplacements.mjs\n        ]\n    },\n    {\n        src : 'src/bot-detection/bot-detection.js',\n        dest :'src/bot-detection/bot-detection.mjs',\n        title : 'Generated ESM version of ua-parser-js/bot-detection',\n        replacements : [...defaultReplacements.mjs]\n    },\n    {\n        src : 'src/browser-detection/browser-detection.js',\n        dest :'src/browser-detection/browser-detection.mjs',\n        title : 'Generated ESM version of ua-parser-js/browser-detection',\n        replacements : [...defaultReplacements.mjs]\n    },\n    {\n        src : 'src/device-detection/device-detection.js',\n        dest :'src/device-detection/device-detection.mjs',\n        title : 'Generated ESM version of ua-parser-js/device-detection',\n        replacements : [...defaultReplacements.mjs]\n    },\n    {\n        src : 'src/enums/ua-parser-enums.js',\n        dest :'src/enums/ua-parser-enums.mjs',\n        title : 'Generated ESM version of ua-parser-js/enums',\n        replacements : [...defaultReplacements.mjs]\n    },\n    {\n        src : 'src/enums/ua-parser-enums.js',\n        dest :'src/enums/ua-parser-enums.d.ts',\n        title : 'Generated type declarations of ua-parser-js/enums',\n        replacements : [\n            [/(const .+) = object\\.freeze\\(/ig, 'export $1: Readonly<'],\n            [/(const .+) =( .+;)/ig, 'export $1: typeof$2'],\n            [/}\\);/ig, '}>;'],\n            [/module\\.exports =.+/igs, '']\n        ]\n    },\n    {\n        src : 'src/extensions/ua-parser-extensions.js',\n        dest : 'src/extensions/ua-parser-extensions.mjs',\n        title : 'Generated ESM version of ua-parser-js/extensions',\n        replacements : [...defaultReplacements.mjs]\n    },\n    {\n        src : 'src/helpers/ua-parser-helpers.js',\n        dest : 'src/helpers/ua-parser-helpers.mjs',\n        title : 'Generated ESM version of ua-parser-js/helpers',\n        replacements : [...defaultReplacements.mjs]\n    }\n];\n\nfiles.forEach(module => generateFile(module));"
  },
  {
    "path": "script/cli.js",
    "content": "#!/usr/bin/env node\n\ntry {    \n    const fs = require('node:fs');\n    const path = require('node:path');\n    const { performance } = require('node:perf_hooks');\n    const readline = require('node:readline');\n    const { parseArgs } = require('node:util');\n    const UAParser = require('../src/main/ua-parser');\n    const { Bots, Emails, ExtraDevices, InApps, Vehicles } = require('../src/extensions/ua-parser-extensions');\n\n    if (!process.argv[2].startsWith('-')) {\n\n        const results = process.argv.slice(2).map(ua => UAParser(ua, [Bots, Emails, ExtraDevices, InApps, Vehicles]));\n        console.log(JSON.stringify(results, null, 4));\n        process.exit(0);\n\n    } else if (['-h', '--help'].includes(process.argv[2])) {\n\n        console.log('Usage: npx ua-parser-js <string>');\n        console.log('   or  npx ua-parser-js --input-file <filepath> [--output-file <filepath>]');\n        console.log('-i, --input-file');\n        console.log('-o, --output-file');\n        process.exit(0);\n\n    } else {\n\n        const startPerf = performance.now();\n        const {\n            values: { \n                'input-file': inputFile, \n                'output-file': outputFile \n            },\n        } = parseArgs({\n            options: {\n                'input-file': { type: 'string', short: 'i' },\n                'output-file': { type: 'string', short: 'o' }\n            }\n        });\n\n        if (!inputFile) {\n            console.error('Input file must be present');\n            process.exit(1);\n        }\n\n        const inputPath = path.resolve(__dirname, inputFile);\n        const outputPath = outputFile ? path.resolve(__dirname, outputFile) : null;\n\n        if (!fs.existsSync(inputPath)) {\n            console.error(`Input file not found: ${inputPath}`);\n            process.exit(1);\n        }\n\n        const inputStream = fs.createReadStream(inputPath, 'utf8');\n        const rl = readline.createInterface({\n            input: inputStream,\n            crlfDelay: Infinity\n        });\n\n        const outputStream = outputPath ? fs.createWriteStream(outputPath, { encoding : 'utf8' }) : process.stdout;\n\n        const uap = new UAParser([Bots, Emails, ExtraDevices, InApps, Vehicles]);\n        let lineNumber = 0;\n\n        outputStream.write('[\\n');\n\n        rl.on('line', line => {\n            const result = uap.setUA(line).getResult();\n            const json = JSON.stringify(result, null, 4);\n            if (lineNumber > 0) outputStream.write(',\\n');\n            outputStream.write(json);\n            lineNumber++;\n        });\n\n        rl.on('close', () => {\n            outputStream.write('\\n]');\n            if (outputPath) {\n                outputStream.end(() => {\n                    const finishPerf = performance.now();\n                    console.log(`Done!`);\n                    console.log(`Number of lines found: ${lineNumber}`);\n                    console.log(`Task finished in: ${(finishPerf - startPerf).toFixed(3)}ms`);\n                    console.log(`Output written to: ${outputPath}`);\n                    process.exit(0);\n                });\n            } else {\n                process.exit(0);\n            }\n        });\n    }\n} catch (err) {\n    console.error(err);\n    process.exit(1);\n}"
  },
  {
    "path": "script/test-all.sh",
    "content": "#!/usr/bin/env bash\n\necho '\n- run build\n'\nnpm run build || exit 1\n\necho '\n- lint js code\n'\nnpm run test:jshint || exit 1 \nnpm run test:eslint || exit 1 \n\necho '\n- test using mocha\n'\nnpm run test:mocha || exit 1 \n\necho '\n- test using playwright\n'\nnpm run test:playwright || exit 1 \n\necho '\n- lint lockfile\n'\nnpm run test:lockfile-lint || exit 1 \n\necho '\n- lint d.ts files\n'\nnpm run test:dts-lint || exit 1"
  },
  {
    "path": "src/bot-detection/bot-detection.d.ts",
    "content": "// Type definitions for bot-detection submodule of UAParser.js v2.0.9\n// Project: https://github.com/faisalman/ua-parser-js\n// Definitions by: Faisal Salman <https://github.com/faisalman>\n\nimport type { IResult } from \"../main/ua-parser\";\n\nexport function isAIAssistant(resultOrUA: IResult | string): boolean;\nexport function isAICrawler(resultOrUA: IResult | string): boolean;\nexport function isBot(resultOrUA: IResult | string): boolean;"
  },
  {
    "path": "src/bot-detection/bot-detection.js",
    "content": "//////////////////////////////////////////////////\n/*  bot-detection submodule of UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n/////////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst { UAParser } = require('../main/ua-parser');\nconst { Bots, Crawlers, Fetchers } = require('../extensions/ua-parser-extensions');\nconst { BrowserType, Extension } = require('../enums/ua-parser-enums');\nconst { Crawler, Fetcher } = Extension.BrowserName;\n\nclass BotList {\n    constructor(ext, prop, list) {\n        this.ext = ext;\n        this.prop = prop;\n        this.list = list.map(x => x.toLowerCase());\n    }\n    includes(ua) {\n        return this.list.includes(\n            (typeof ua === 'string' ? \n                new UAParser(ua, this.ext).getBrowser() : \n                ua.browser\n            )[this.prop]?.toLowerCase());\n    }\n}\n\nconst BotTypes = new BotList(Bots, 'type', [\n    BrowserType.CLI, \n    BrowserType.CRAWLER, \n    BrowserType.FETCHER, \n    BrowserType.LIBRARY\n]);\n\nconst AIAssistants = new BotList(Fetchers, 'name', [\n\n    // Amazon\n    Fetcher.AMAZON_NOVA_ACT,\n\n    // Anthropic\n    Fetcher.ANTHROPIC_CLAUDE_USER,\n\n    // Cohere\n    Fetcher.COHERE_AI,\n\n    // DuckDuckGo\n    Fetcher.DUCKDUCKGO_ASSISTBOT,\n\n    // Google\n    Fetcher.GOOGLE_GEMINI_DEEP_RESEARCH,\n\n    // Mistral AI\n    Fetcher.MISTRALAI_USER,\n\n    // OpenAI\n    Fetcher.OPENAI_CHATGPT_USER,\n\n    // Perplexity\n    Fetcher.PERPLEXITY_USER\n]);\n\nconst AICrawlers = new BotList(Crawlers, 'name', [\n\n    // AI2\n    Crawler.AI2_BOT,\n\n    // Amazon\n    Crawler.AMAZON_BOT,\n\n    // Anthropic\n    Crawler.ANTHROPIC_AI,\n    Crawler.ANTHROPIC_CLAUDE_BOT,\n    Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,\n    Crawler.ANTHROPIC_CLAUDE_WEB,\n\n    // Apple\n    Crawler.APPLE_BOT,\n    Crawler.APPLE_BOT_EXTENDED,\n\n    // Atlassian\n    Crawler.ATLASSIAN_BOT,\n\n    // Brave\n    Crawler.BRAVE_BOT,\n\n    // ByteDance\n    Crawler.BYTEDANCE_BYTESPIDER,\n    Crawler.BYTEDANCE_TIKTOKSPIDER,\n\n    // Cloudflare\n    Crawler.CLOUDFLARE_AUTORAG,\n\n    // Cohere\n    Crawler.COHERE_TRAINING_DATA_CRAWLER,\n\n    // Common Crawl\n    Crawler.COMMON_CRAWL_CCBOT,    \n\n    // Coveo\n    Crawler.COVEO_BOT,\n\n    // DataForSeo\n    Crawler.DATAFORSEO_BOT,\n\n    // DeepSeek\n    Crawler.DEEPSEEK_BOT,\n\n    // Diffbot\n    Crawler.DIFFBOT,\n\n    // Google\n    Crawler.GOOGLE_EXTENDED,\n    Crawler.GOOGLE_NOTEBOOKLM,\n    Crawler.GOOGLE_OTHER,\n    Crawler.GOOGLE_OTHER_IMAGE,\n    Crawler.GOOGLE_OTHER_VIDEO,\n    Crawler.GOOGLE_CLOUDVERTEXBOT,\n\n    // Hive AI\n    Crawler.HIVE_IMAGESIFTBOT,\n\n    // Huawei\n    Crawler.HUAWEI_PETALBOT,\n    Crawler.HUAWEI_PANGUBOT,\n\n    // Hugging Face\n    Crawler.HUGGINGFACE_BOT,\n\n    // Kangaroo\n    Crawler.KANGAROO_BOT,\n\n    // Mendable.ai\n    Crawler.FIRECRAWL_AGENT,\n\n    // Meta\n    Crawler.META_FACEBOOKBOT,\n    Crawler.META_EXTERNALAGENT,\n    Crawler.META_WEBINDEXER,\n\n    // OpenAI\n    Crawler.OPENAI_GPTBOT,\n    Crawler.OPENAI_SEARCH_BOT,\n\n    // Perplexity\n    Crawler.PERPLEXITY_BOT,\n\n    // Replicate\n    Crawler.REPLICATE_BOT,\n\n    // Runpod\n    Crawler.RUNPOD_BOT,\n\n    // SB Intuitions\n    Crawler.SB_INTUITIONS_BOT,\n\n    // Semrush\n    Crawler.SEMRUSH_BOT_CONTENTSHAKE,\n    Crawler.SEMRUSH_BOT_SWA,\n\n    // Timpi\n    Crawler.TIMPI_BOT,\n\n    // Together AI\n    Crawler.TOGETHER_BOT,\n\n    // Velen.io\n    Crawler.HUNTER_VELENPUBLICWEBCRAWLER,\n\n    // Vercel\n    Crawler.VERCEL_V0BOT,\n\n    // Webz.io\n    Crawler.WEBZIO_OMGILI,\n    Crawler.WEBZIO_OMGILI_BOT,\n    Crawler.WEBZIO_EXTENDED,\n\n    // X\n    Crawler.XAI_BOT,\n\n    // You.com\n    Crawler.YOU_BOT,\n\n    // Zhipu AI\n    Crawler.ZHIPU_CHATGLM_SPIDER\n]);\n\nconst isBot = ua => BotTypes.includes(ua);\nconst isAIAssistant = ua => AIAssistants.includes(ua);\nconst isAICrawler = ua => AICrawlers.includes(ua);\n\nmodule.exports = {\n    isAIAssistant, \n    isAICrawler,\n    isBot\n}"
  },
  {
    "path": "src/bot-detection/bot-detection.mjs",
    "content": "// Generated ESM version of ua-parser-js/bot-detection\n// DO NOT EDIT THIS FILE!\n// Source: /src/bot-detection/bot-detection.js\n\n//////////////////////////////////////////////////\n/*  bot-detection submodule of UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n/////////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nimport { UAParser } from '../main/ua-parser.mjs';\nimport { Bots, Crawlers, Fetchers } from '../extensions/ua-parser-extensions.mjs';\nimport { BrowserType, Extension } from '../enums/ua-parser-enums.mjs';\nconst { Crawler, Fetcher } = Extension.BrowserName;\n\nclass BotList {\n    constructor(ext, prop, list) {\n        this.ext = ext;\n        this.prop = prop;\n        this.list = list.map(x => x.toLowerCase());\n    }\n    includes(ua) {\n        return this.list.includes(\n            (typeof ua === 'string' ? \n                new UAParser(ua, this.ext).getBrowser() : \n                ua.browser\n            )[this.prop]?.toLowerCase());\n    }\n}\n\nconst BotTypes = new BotList(Bots, 'type', [\n    BrowserType.CLI, \n    BrowserType.CRAWLER, \n    BrowserType.FETCHER, \n    BrowserType.LIBRARY\n]);\n\nconst AIAssistants = new BotList(Fetchers, 'name', [\n\n    // Amazon\n    Fetcher.AMAZON_NOVA_ACT,\n\n    // Anthropic\n    Fetcher.ANTHROPIC_CLAUDE_USER,\n\n    // Cohere\n    Fetcher.COHERE_AI,\n\n    // DuckDuckGo\n    Fetcher.DUCKDUCKGO_ASSISTBOT,\n\n    // Google\n    Fetcher.GOOGLE_GEMINI_DEEP_RESEARCH,\n\n    // Mistral AI\n    Fetcher.MISTRALAI_USER,\n\n    // OpenAI\n    Fetcher.OPENAI_CHATGPT_USER,\n\n    // Perplexity\n    Fetcher.PERPLEXITY_USER\n]);\n\nconst AICrawlers = new BotList(Crawlers, 'name', [\n\n    // AI2\n    Crawler.AI2_BOT,\n\n    // Amazon\n    Crawler.AMAZON_BOT,\n\n    // Anthropic\n    Crawler.ANTHROPIC_AI,\n    Crawler.ANTHROPIC_CLAUDE_BOT,\n    Crawler.ANTHROPIC_CLAUDE_SEARCHBOT,\n    Crawler.ANTHROPIC_CLAUDE_WEB,\n\n    // Apple\n    Crawler.APPLE_BOT,\n    Crawler.APPLE_BOT_EXTENDED,\n\n    // Atlassian\n    Crawler.ATLASSIAN_BOT,\n\n    // Brave\n    Crawler.BRAVE_BOT,\n\n    // ByteDance\n    Crawler.BYTEDANCE_BYTESPIDER,\n    Crawler.BYTEDANCE_TIKTOKSPIDER,\n\n    // Cloudflare\n    Crawler.CLOUDFLARE_AUTORAG,\n\n    // Cohere\n    Crawler.COHERE_TRAINING_DATA_CRAWLER,\n\n    // Common Crawl\n    Crawler.COMMON_CRAWL_CCBOT,    \n\n    // Coveo\n    Crawler.COVEO_BOT,\n\n    // DataForSeo\n    Crawler.DATAFORSEO_BOT,\n\n    // DeepSeek\n    Crawler.DEEPSEEK_BOT,\n\n    // Diffbot\n    Crawler.DIFFBOT,\n\n    // Google\n    Crawler.GOOGLE_EXTENDED,\n    Crawler.GOOGLE_NOTEBOOKLM,\n    Crawler.GOOGLE_OTHER,\n    Crawler.GOOGLE_OTHER_IMAGE,\n    Crawler.GOOGLE_OTHER_VIDEO,\n    Crawler.GOOGLE_CLOUDVERTEXBOT,\n\n    // Hive AI\n    Crawler.HIVE_IMAGESIFTBOT,\n\n    // Huawei\n    Crawler.HUAWEI_PETALBOT,\n    Crawler.HUAWEI_PANGUBOT,\n\n    // Hugging Face\n    Crawler.HUGGINGFACE_BOT,\n\n    // Kangaroo\n    Crawler.KANGAROO_BOT,\n\n    // Mendable.ai\n    Crawler.FIRECRAWL_AGENT,\n\n    // Meta\n    Crawler.META_FACEBOOKBOT,\n    Crawler.META_EXTERNALAGENT,\n\n    // OpenAI\n    Crawler.OPENAI_GPTBOT,\n    Crawler.OPENAI_SEARCH_BOT,\n\n    // Perplexity\n    Crawler.PERPLEXITY_BOT,\n\n    // Replicate\n    Crawler.REPLICATE_BOT,\n\n    // Runpod\n    Crawler.RUNPOD_BOT,\n\n    // SB Intuitions\n    Crawler.SB_INTUITIONS_BOT,\n\n    // Semrush\n    Crawler.SEMRUSH_BOT_CONTENTSHAKE,\n    Crawler.SEMRUSH_BOT_SWA,\n\n    // Timpi\n    Crawler.TIMPI_BOT,\n\n    // Together AI\n    Crawler.TOGETHER_BOT,\n\n    // Velen.io\n    Crawler.HUNTER_VELENPUBLICWEBCRAWLER,\n\n    // Vercel\n    Crawler.VERCEL_V0BOT,\n\n    // Webz.io\n    Crawler.WEBZIO_OMGILI,\n    Crawler.WEBZIO_OMGILI_BOT,\n    Crawler.WEBZIO_EXTENDED,\n\n    // X\n    Crawler.XAI_BOT,\n\n    // You.com\n    Crawler.YOU_BOT,\n\n    // Zhipu AI\n    Crawler.ZHIPU_CHATGLM_SPIDER\n]);\n\nconst isBot = ua => BotTypes.includes(ua);\nconst isAIAssistant = ua => AIAssistants.includes(ua);\nconst isAICrawler = ua => AICrawlers.includes(ua);\n\nexport {\n    isAIAssistant, \n    isAICrawler,\n    isBot\n}"
  },
  {
    "path": "src/browser-detection/browser-detection.d.ts",
    "content": "// Type definitions for browser-detection submodule of UAParser.js v2.0.9\n// Project: https://github.com/faisalman/ua-parser-js\n// Definitions by: Faisal Salman <https://github.com/faisalman>\n\nimport type { IResult } from \"../main/ua-parser\";\n\nexport function isChromeFamily(resultOrUA: IResult | string): boolean;\nexport function isElectron(): boolean;\nexport function isFromEU(): boolean;\nexport function isStandalonePWA(): boolean;"
  },
  {
    "path": "src/browser-detection/browser-detection.js",
    "content": "//////////////////////////////////////////////////////\n/*  browser-detection submodule of UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n/////////////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst { UAParser } = require('../main/ua-parser');\nconst { EngineName } = require('../enums/ua-parser-enums');\nconst { isStandalonePWA } = require('is-standalone-pwa');\nconst { isFromEU } = require('detect-europe-js');\n\nconst isChromeFamily = val => !!(\n    (typeof val === 'string' ? \n        new UAParser(val).getEngine() : \n        val.engine\n    )?.is(EngineName.BLINK));\n\nconst isElectron = () => !!(\n    process?.versions?.hasOwnProperty('electron') ||    // node.js\n    / electron\\//i.test(navigator?.userAgent));         // browser\n\nmodule.exports = { \n    isChromeFamily,\n    isElectron,\n    isFromEU,\n    isStandalonePWA\n}"
  },
  {
    "path": "src/browser-detection/browser-detection.mjs",
    "content": "// Generated ESM version of ua-parser-js/browser-detection\n// DO NOT EDIT THIS FILE!\n// Source: /src/browser-detection/browser-detection.js\n\n//////////////////////////////////////////////////////\n/*  browser-detection submodule of UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n/////////////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nimport { UAParser } from '../main/ua-parser.mjs';\nimport { EngineName } from '../enums/ua-parser-enums.mjs';\nimport { isStandalonePWA } from 'is-standalone-pwa';\nimport { isFromEU } from 'detect-europe-js';\n\nconst isChromeFamily = val => !!(\n    (typeof val === 'string' ? \n        new UAParser(val).getEngine() : \n        val.engine\n    )?.is(EngineName.BLINK));\n\nconst isElectron = () => !!(\n    process?.versions?.hasOwnProperty('electron') ||    // node.js\n    / electron\\//i.test(navigator?.userAgent));         // browser\n\nexport { \n    isChromeFamily,\n    isElectron,\n    isFromEU,\n    isStandalonePWA\n}"
  },
  {
    "path": "src/device-detection/device-detection.d.ts",
    "content": "// Type definitions for device-detection submodule of UAParser.js v2.0.9\n// Project: https://github.com/faisalman/ua-parser-js\n// Definitions by: Faisal Salman <https://github.com/faisalman>\n\nimport type { IResult } from \"../main/ua-parser\";\n\nexport function getDeviceVendor(model: string): string | undefined;\nexport function isAppleSilicon(resultOrUA: IResult | string): boolean;"
  },
  {
    "path": "src/device-detection/device-detection.js",
    "content": "/////////////////////////////////////////////////////\n/*  device-detection submodule of UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n////////////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst { UAParser } = require('../main/ua-parser');\nconst { CPUArch, OSName  } = require('../enums/ua-parser-enums');\n\nconst getDeviceVendor = (model) => new UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).getDevice().vendor;\n\nconst isAppleSilicon = (val) => {\n    const { os, cpu } = typeof val !== 'string' ? val : {\n        os: new UAParser(val).getOS(),\n        cpu: new UAParser(val).getCPU() \n    };\n    if (os.is(OSName.MACOS)) {\n        if (cpu.is(CPUArch.ARM)) {\n            return true;\n        } else if (typeof window !== 'undefined') {\n            try {\n                const canvas = document.createElement('canvas');\n                const webgl = canvas.getContext('webgl2') || \n                                canvas.getContext('webgl') || \n                                canvas.getContext('experimental-webgl');\n                return webgl\n                        .getParameter(webgl.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL)\n                        .match(/apple m\\d/i);\n            } catch {\n                return false;\n            }\n        }\n    }\n    return false;\n}\n\nmodule.exports = { \n    getDeviceVendor,\n    isAppleSilicon\n}"
  },
  {
    "path": "src/device-detection/device-detection.mjs",
    "content": "// Generated ESM version of ua-parser-js/device-detection\n// DO NOT EDIT THIS FILE!\n// Source: /src/device-detection/device-detection.js\n\n/////////////////////////////////////////////////////\n/*  device-detection submodule of UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n////////////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nimport { UAParser } from '../main/ua-parser.mjs';\nimport { CPUArch, OSName  } from '../enums/ua-parser-enums.mjs';\n\nconst getDeviceVendor = (model) => new UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).getDevice().vendor;\n\nconst isAppleSilicon = (val) => {\n    const { os, cpu } = typeof val !== 'string' ? val : {\n        os: new UAParser(val).getOS(),\n        cpu: new UAParser(val).getCPU() \n    };\n    if (os.is(OSName.MACOS)) {\n        if (cpu.is(CPUArch.ARM)) {\n            return true;\n        } else if (typeof window !== 'undefined') {\n            try {\n                const canvas = document.createElement('canvas');\n                const webgl = canvas.getContext('webgl2') || \n                                canvas.getContext('webgl') || \n                                canvas.getContext('experimental-webgl');\n                return webgl\n                        .getParameter(webgl.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL)\n                        .match(/apple m\\d/i);\n            } catch {\n                return false;\n            }\n        }\n    }\n    return false;\n}\n\nexport { \n    getDeviceVendor,\n    isAppleSilicon\n}"
  },
  {
    "path": "src/enums/ua-parser-enums.d.ts",
    "content": "// Generated type declarations of ua-parser-js/enums\n// DO NOT EDIT THIS FILE!\n// Source: /src/enums/ua-parser-enums.js\n\n///////////////////////////////////////////////\n/*  Enums for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nexport const BrowserName: Readonly<{\n    '115': '115',\n    '2345': '2345',\n    '360': '360',\n    ALIPAY: 'Alipay',\n    ALOHA: 'Aloha',\n    AMAYA: 'Amaya',\n    ANDROID: 'Android Browser',\n    ARORA: 'Arora',\n    ATLAS: 'Atlas',\n    AVANT: 'Avant',\n    AVAST: 'Avast Secure Browser',\n    AVG: 'AVG Secure Browser',\n    AVIRA: 'Avira Secure Browser',\n    BAIDU: 'Baidu Browser',\n    BASILISK: 'Basilisk',\n    BING: 'Bing',\n    BLAZER: 'Blazer',\n    BOLT: 'Bolt',\n    BOWSER: 'Bowser',\n    BRAVE: 'Brave',\n    CAMINO: 'Camino',\n    CHIMERA: 'Chimera',\n    CHROME: 'Chrome',\n    CHROME_HEADLESS: 'Chrome Headless',\n    CHROME_MOBILE: 'Mobile Chrome',\n    CHROME_WEBVIEW: 'Chrome WebView',\n    CHROMIUM: 'Chromium',\n    COBALT: 'Cobalt',\n    COC_COC: 'Coc Coc',\n    CONKEROR: 'Conkeror',\n    DAUM: 'Daum',\n    DILLO: 'Dillo',\n    DOLPHIN: 'Dolphin',\n    DOOBLE: 'Dooble',\n    DORIS: 'Doris',\n    DRAGON: 'Dragon',\n    DUCKDUCKGO: 'DuckDuckGo',\n    ECOSIA: 'Ecosia',\n    EDGE: 'Edge',\n    EDGE_WEBVIEW: 'Edge WebView',\n    EDGE_WEBVIEW2: 'Edge WebView2',\n    EPIPHANY: 'Epiphany',\n    FACEBOOK: 'Facebook',\n    FALKON: 'Falkon',\n    FIREBIRD: 'Firebird',\n    FIREFOX: 'Firefox',\n    FIREFOX_FOCUS: 'Firefox Focus',\n    FIREFOX_MOBILE: 'Mobile Firefox',\n    FIREFOX_REALITY: 'Firefox Reality',\n    FENNEC: 'Fennec',\n    FLOCK: 'Flock',\n    FLOW: 'Flow',\n    GO: 'GoBrowser',\n    GOOGLE_SEARCH: 'GSA',\n    HELIO: 'Helio',\n    HEYTAP: 'HeyTap',\n    HIBROWSER: 'HiBrowser',\n    HONOR: 'Honor',\n    HUAWEI: 'Huawei Browser',\n    ICAB: 'iCab',\n    ICE: 'ICE Browser',\n    ICEAPE: 'IceApe',\n    ICECAT: 'IceCat',\n    ICEDRAGON: 'IceDragon',\n    ICEWEASEL: 'IceWeasel',\n    IE: 'IE',\n    INSTAGRAM: 'Instagram',\n    IRIDIUM: 'Iridium',\n    IRON: 'Iron',\n    JASMINE: 'Jasmine',\n    KONQUEROR: 'Konqueror',\n    KAKAO: 'KakaoTalk',\n    KHTML: 'KHTML',\n    K_MELEON: 'K-Meleon',\n    KLAR: 'Klar',\n    KLARNA: 'Klarna',\n    KINDLE: 'Kindle',\n    LENOVO: 'Smart Lenovo Browser',\n    LADYBIRD: 'Ladybird',\n    LG: 'LG Browser',\n    LIBREWOLF: 'LibreWolf',\n    LIEBAO: 'LBBROWSER',\n    LIGHTHOUSE: 'Lighthouse',\n    LINE: 'Line',\n    LINKEDIN: 'LinkedIn',\n    LINKS: 'Links',\n    LUAKIT: 'Luakit',\n    LUNASCAPE: 'Lunascape',\n    LYNX: 'Lynx',\n    MAEMO: 'Maemo Browser',\n    MAXTHON: 'Maxthon',\n    MIDORI: 'Midori',\n    MINIMO: 'Minimo',\n    MIUI: 'MIUI Browser',\n    MOZILLA: 'Mozilla',\n    MOSAIC: 'Mosaic',\n    NAVER: 'Naver',\n    NETFRONT: 'NetFront',\n    NETSCAPE: 'Netscape',\n    NETSURF: 'Netsurf',\n    NOKIA: 'Nokia Browser',\n    NORTON: 'Norton Private Browser',\n    OBIGO: 'Obigo',\n    OCULUS: 'Oculus Browser',\n    OMNIWEB: 'OmniWeb',\n    OPERA: 'Opera',\n    OPERA_COAST: 'Opera Coast',\n    OPERA_GX: 'Opera GX',\n    OPERA_MINI: 'Opera Mini',\n    OPERA_MOBI: 'Opera Mobi',\n    OPERA_NEON: 'Opera Neon',\n    OPERA_TABLET: 'Opera Tablet',\n    OPERA_TOUCH: 'Opera Touch',\n    OTTER: 'Otter',\n    OVI: 'OviBrowser',\n    PALEMOON: 'PaleMoon',\n    PHANTOMJS: 'PhantomJS',\n    PHOENIX: 'Phoenix',\n    PICOBROWSER: 'Pico Browser',\n    POLARIS: 'Polaris',\n    PUFFIN: 'Puffin',\n    QQ: 'QQBrowser',\n    QQ_LITE: 'QQBrowserLite',\n    QUARK: 'Quark',\n    QUPZILLA: 'QupZilla',\n    QUTEBROWSER: 'qutebrowser',\n    QWANT: 'Qwant',\n    REKONQ: 'rekonq',\n    ROCKMELT: 'Rockmelt',\n    SAFARI: 'Safari',\n    SAFARI_MOBILE: 'Mobile Safari',\n    SAILFISH: 'Sailfish Browser',\n    SAMSUNG: 'Samsung Internet',\n    SEAMONKEY: 'SeaMonkey',\n    SILK: 'Silk',\n    SKYFIRE: 'Skyfire',\n    SLEIPNIR: 'Sleipnir',\n    SLIMBOAT: 'SlimBoat',\n    SLIMBROWSER: 'SlimBrowser',\n    SLIMJET: 'Slimjet',\n    SNAPCHAT: 'Snapchat',\n    SOGOU_EXPLORER: 'Sogou Explorer',\n    SOGOU_MOBILE: 'Sogou Mobile',\n    STEAM: 'Steam',\n    SURF: 'Surf',\n    SWIFTFOX: 'Swiftfox',\n    TESLA: 'Tesla',\n    TIKTOK: 'TikTok',\n    TIZEN: 'Tizen Browser',\n    TWITTER: 'Twitter',\n    UC: 'UCBrowser',\n    UP: 'UP.Browser',\n    VIVALDI: 'Vivaldi',\n    VIVO: 'Vivo Browser',\n    W3M: 'w3m',\n    WATERFOX: 'Waterfox',\n    WEBKIT: 'WebKit',\n    WECHAT: 'WeChat',\n    WEIBO: 'Weibo',\n    WHALE: 'Whale',\n    WOLVIC: 'Wolvic',\n    YANDEX: 'Yandex',\n    ZALO: 'Zalo'\n\n    // TODO : test!\n}>;\n/**\n * @deprecated Use `BrowserName` instead\n */\nexport const Browser: typeof BrowserName;\n\nexport const BrowserType: Readonly<{\n    CRAWLER: 'crawler',\n    CLI: 'cli',\n    EMAIL: 'email',\n    FETCHER: 'fetcher',\n    INAPP: 'inapp',\n    MEDIAPLAYER: 'mediaplayer',\n    LIBRARY: 'library'\n}>;\n\nexport const CPUArch: Readonly<{\n    '68K': '68k',\n    ALPHA: 'alpha',\n    ARM : 'arm',\n    ARM_64: 'arm64',\n    ARM_HF: 'armhf',\n    AVR: 'avr',\n    AVR_32: 'avr32',\n    IA64: 'ia64',\n    IRIX: 'irix',\n    IRIX_64: 'irix64',\n    MIPS: 'mips',\n    MIPS_64: 'mips64',\n    PA_RISC: 'pa-risc',\n    PPC: 'ppc',\n    SPARC: 'sparc',\n    SPARC_64: 'sparc64',\n    X86: 'ia32',\n    X86_64: 'amd64'\n}>;\n/**\n * @deprecated Use `CPUArch` instead\n */\nexport const CPU: typeof CPUArch;\n\nexport const DeviceType: Readonly<{\n    CONSOLE: 'console',\n    EMBEDDED: 'embedded',\n    MOBILE: 'mobile',\n    SMARTTV: 'smarttv',\n    TABLET: 'tablet',\n    WEARABLE: 'wearable',\n    XR: 'xr'\n}>;\n/**\n * @deprecated Use `DeviceType` instead\n */\nexport const Device: typeof DeviceType;\n\nexport const DeviceVendor: Readonly<{\n    ACER: 'Acer',\n    ADVAN: 'Advan',\n    ALCATEL: 'Alcatel',\n    AMAZON: 'Amazon',\n    ANBERNIC: 'Anbernic',\n    APPLE: 'Apple',\n    ARCHOS: 'Archos',\n    ASUS: 'ASUS',\n    ATT: 'AT&T',\n    BENQ: 'BenQ',\n    BLACKBERRY: 'BlackBerry',\n    BLU: 'BLU',\n    CAT: 'Cat',\n    DELL: 'Dell',\n    ENERGIZER: 'Energizer',\n    ESSENTIAL: 'Essential',\n    FACEBOOK: 'Facebook',\n    FAIRPHONE: 'Fairphone',\n    GEEKSPHONE: 'GeeksPhone',\n    GENERIC: 'Generic',\n    GOOGLE: 'Google',\n    HISENSE: 'Hisense',\n    HMD: 'HMD',\n    HP: 'HP',\n    HTC: 'HTC',\n    HUAWEI: 'Huawei',\n    IMO: 'IMO',\n    INFINIX: 'Infinix',\n    ITEL: 'itel',\n    JOLLA: 'Jolla',\n    KOBO: 'Kobo',\n    LAVA: 'Lava',\n    LENOVO: 'Lenovo',\n    LG: 'LG',\n    LOGITECH: 'Logitech',\n    MEIZU: 'Meizu',\n    MICROMAX: 'Micromax',\n    MICROSOFT: 'Microsoft',\n    MOTOROLA: 'Motorola',\n    NEXIAN: 'Nexian',\n    NINTENDO: 'Nintendo',\n    NOKIA: 'Nokia',\n    NOTHING: 'Nothing',\n    NVIDIA: 'Nvidia',\n    ONEPLUS: 'OnePlus',\n    OPPO: 'OPPO',\n    OUYA: 'Ouya',\n    PALM: 'Palm',\n    PANASONIC: 'Panasonic',\n    PEBBLE: 'Pebble',\n    PHILIPS: 'Philips',\n    PICO: 'Pico',\n    POLYTRON: 'Polytron',\n    REALME: 'Realme',\n    RETROID: 'Retroid',\n    RIM: 'RIM',\n    ROKU: 'Roku',\n    SAMSUNG: 'Samsung',\n    SHARP: 'Sharp',\n    SIEMENS: 'Siemens',\n    SMARTFREN: 'Smartfren',\n    SONY: 'Sony',\n    SPRINT: 'Sprint',\n    TCL: 'TCL',\n    TECHNISAT: 'TechniSAT',\n    TECNO: 'TECNO',\n    TESLA: 'Tesla',\n    ULEFONE: 'Ulefone',\n    VALVE: 'Valve',\n    VIVO: 'Vivo',\n    VIZIO: 'Vizio',\n    VODAFONE: 'Vodafone',\n    WIKO: 'Wiko',\n    XBOX: 'Xbox',\n    XIAOMI: 'Xiaomi',\n    ZEBRA: 'Zebra',\n    ZTE: 'ZTE',\n\n    // TODO : test!\n}>;\n/**\n * @deprecated Use `DeviceVendor` instead\n */\nexport const Vendor: typeof DeviceVendor;\n\nexport const EngineName: Readonly<{\n    AMAYA: 'Amaya',\n    ARKWEB: 'ArkWeb',\n    BLINK: 'Blink',\n    DILLO: 'Dillo',\n    EDGEHTML: 'EdgeHTML',\n    FLOW: 'Flow',\n    GECKO: 'Gecko',\n    GOANNA: 'Goanna',\n    ICAB: 'iCab',\n    KHTML: 'KHTML',\n    LIBWEB: 'LibWeb',\n    LINKS: 'Links',\n    LYNX: 'Lynx',\n    NETFRONT: 'NetFront',\n    NETSURF: 'NetSurf',\n    PRESTO: 'Presto',\n    SERVO: 'Servo',\n    TASMAN: 'Tasman',\n    TRIDENT: 'Trident',\n    W3M: 'w3m',\n    WEBKIT: 'WebKit'\n}>;\n/**\n * @deprecated Use `EngineName` instead\n */\nexport const Engine: typeof EngineName;\n\nexport const OSName: Readonly<{\n    AIX: 'AIX',\n    AMIGA_OS: 'Amiga OS',\n    ANDROID: 'Android',\n    ANDROID_X86: 'Android-x86',\n    ARCAOS: 'ArcaOS',\n    ARCH: 'Arch',\n    BADA: 'Bada',\n    BEOS: 'BeOS',\n    BLACKBERRY: 'BlackBerry',\n    CENTOS: 'CentOS',\n    CHROME_OS: 'Chrome OS',\n    CHROMECAST: 'Chromecast',\n    CHROMECAST_ANDROID: 'Chromecast Android',\n    CHROMECAST_FUCHSIA: 'Chromecast Fuchsia',\n    CHROMECAST_LINUX: 'Chromecast Linux',\n    CHROMECAST_SMARTSPEAKER: 'Chromecast SmartSpeaker',\n    CONTIKI: 'Contiki',\n    DEBIAN: 'Debian',\n    DEEPIN: 'Deepin',\n    DRAGONFLY: 'DragonFly',\n    ELEMENTARY_OS: 'elementary OS',\n    FEDORA: 'Fedora',\n    FIREFOX_OS: 'Firefox OS',\n    FREEBSD: 'FreeBSD',\n    FUCHSIA: 'Fuchsia',\n    GENTOO: 'Gentoo',\n    GHOSTBSD: 'GhostBSD',\n    GNU: 'GNU',\n    HAIKU: 'Haiku',\n    HARMONYOS: 'HarmonyOS',\n    HP_UX: 'HP-UX',\n    HURD: 'Hurd',\n    IOS: 'iOS',\n    JOLI: 'Joli',\n    KAIOS: 'KaiOS',\n    KNOPPIX: 'Knoppix',\n    KUBUNTU: 'Kubuntu',\n    LINPUS: 'Linpus',\n    LINSPIRE: 'Linspire',\n    LINUX: 'Linux',\n    MACOS: 'macOS',\n    MAEMO: 'Maemo',\n    MAGEIA: 'Mageia',\n    MANDRIVA: 'Mandriva',\n    MANJARO: 'Manjaro',\n    MEEGO: 'MeeGo',\n    MINIX: 'Minix',\n    MINT: 'Mint',\n    MORPH_OS: 'Morph OS',\n    NETBSD: 'NetBSD',\n    NETRANGE: 'NetRange',\n    NETTV: 'NetTV',\n    NINTENDO: 'Nintendo',\n    OPENHARMONY: 'OpenHarmony',\n    OPENBSD: 'OpenBSD',\n    OPENVMS: 'OpenVMS',\n    OS2: 'OS/2',\n    PALM: 'Palm',\n    PC_BSD: 'PC-BSD',\n    PCLINUXOS: 'PCLinuxOS',\n    PICO: 'Pico',\n    PLAN9: 'Plan9',\n    PLAYSTATION: 'PlayStation',\n    QNX: 'QNX',\n    RASPBIAN: 'Raspbian',\n    REDHAT: 'RedHat',\n    RIM_TABLET_OS: 'RIM Tablet OS',\n    RISC_OS: 'RISC OS',\n    SABAYON: 'Sabayon',\n    SAILFISH: 'Sailfish',\n    SERENITYOS: 'SerenityOS',\n    SERIES40: 'Series40',\n    SLACKWARE: 'Slackware',\n    SOLARIS: 'Solaris',\n    SUSE: 'SUSE',\n    SYMBIAN: 'Symbian',\n    TIZEN: 'Tizen',\n    UBUNTU: 'Ubuntu',\n    UBUNTU_TOUCH: 'Ubuntu Touch',\n    UNIX: 'Unix',\n    VECTORLINUX: 'VectorLinux',\n    VEGA_OS: 'Vega OS',\n    WATCHOS: 'watchOS',\n    WEBOS: 'WebOS',\n    WINDOWS: 'Windows',\n    WINDOWS_CE: 'Windows CE',\n    WINDOWS_IOT: 'Windows IoT',\n    WINDOWS_MOBILE: 'Windows Mobile',\n    WINDOWS_PHONE: 'Windows Phone',\n    WINDOWS_RT: 'Windows RT',\n    XBOX: 'Xbox',\n    XUBUNTU: 'Xubuntu',\n    ZENWALK: 'Zenwalk'\n\n    // TODO : test!\n}>;\n/**\n * @deprecated Use `OSName` instead\n */\nexport const OS: typeof OSName;\n\n/*////////////////////////////////\n * Enums for Extensions submodule\n *///////////////////////////////\n\nexport const Extension: Readonly<{\n    BrowserName: {\n        CLI: {\n            CURL: 'curl',\n            ELINKS: 'ELinks',\n            HTTPIE: 'HTTPie',\n            LYNX: 'Lynx',\n            POWERSHELL: 'PowerShell',\n            WGET: 'Wget'\n        },\n        Crawler: {\n            AHREFS_BOT: 'AhrefsBot',\n            AI2_BOT: 'AI2Bot',\n            AIHIT_BOT: 'aiHitBot',\n            ALGOLIA_CRAWLER: 'Algolia Crawler',\n            APPLE_BOT: 'Applebot',\n            APPLE_BOT_EXTENDED: 'Applebot-Extended',\n            ASK_TEOMA: 'Teoma',\n            AMAZON_BOT: 'Amazonbot',\n            AMAZON_CONTXBOT: 'contxbot',\n            ANTHROPIC_AI: 'anthropic-ai',\n            ANTHROPIC_CLAUDE_BOT: 'ClaudeBot',\n            ANTHROPIC_CLAUDE_SEARCHBOT: 'Claude-SearchBot',\n            ANTHROPIC_CLAUDE_WEB: 'Claude-Web',\n            ATLASSIAN_BOT: 'atlassian-bot',\n            ARCHIVEORG_BOT: 'archive.org_bot',\n            BAIDU_ADS: 'Baidu-ADS',\n            BAIDU_SPIDER: 'Baiduspider',\n            BAIDU_SPIDER_ADS: 'Baiduspider-ads',\n            BAIDU_SPIDER_CPRO: 'Baiduspider-cpro',\n            BAIDU_SPIDER_FAVO: 'Baiduspider-favo',\n            BAIDU_SPIDER_IMAGE: 'Baiduspider-image',\n            BAIDU_SPIDER_NEWS: 'Baiduspider-news',\n            BAIDU_SPIDER_RENDER: 'Baiduspider-render',\n            BAIDU_SPIDER_VIDEO: 'Baiduspider-video',\n            BLEX_BOT: 'BLEXBot',\n            BOTIFY: 'botify',\n            BRAVE_BOT: 'Bravebot',\n            BYTEDANCE_BYTESPIDER: 'Bytespider',\n            BYTEDANCE_TIKTOKSPIDER: 'TikTokSpider',\n            CLOUDFLARE_AUTORAG: 'Cloudflare-AutoRAG',\n            COMMON_CRAWL_CCBOT: 'CCBot',\n            COCCOC_BOT_WEB: 'coccocbot-web',\n            COCCOC_BOT_IMAGE: 'coccocbot-image',\n            COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler',\n            COTOYOGI: 'Cotoyogi',\n            COVEO_BOT: 'Coveobot',\n            CRITEO_BOT: 'CriteoBot',\n            DATAFORSEO_BOT: 'DataForSeoBot',\n            DAUM: 'Daum',\n            DAUM_DAUMOA: 'Daumoa',\n            DAUM_DAUMOA_IMAGE: 'Daumoa-image',\n            DEEPSEEK_BOT: 'DeepSeekBot',\n            DIFFBOT: 'Diffbot',\n            DUCKDUCKGO_BOT: 'DuckDuckBot',\n            DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',\n            ELASTIC: 'Elastic',\n            ELASTIC_SWIFTYPE_BOT: 'Swiftbot',\n            EXALEAD_EXABOT: 'Exabot',\n            FIRECRAWL_AGENT: 'FirecrawlAgent',\n            FREESPOKE: 'Freespoke',\n            GOOGLE_ADSBOT: 'AdsBot-Google',\n            GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile',\n            GOOGLE_ADSENSE: 'AdSense',\n            GOOGLE_APIS: 'APIs-Google',\n            GOOGLE_BOT: 'Googlebot',\n            GOOGLE_BOT_IMAGE: 'Googlebot-Image',\n            GOOGLE_BOT_NEWS: 'Googlebot-News',\n            GOOGLE_BOT_VIDEO: 'Googlebot-Video',\n            GOOGLE_CLOUDVERTEXBOT: 'Google-CloudVertexBot',\n            GOOGLE_EXTENDED: 'Google-Extended',\n            GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool',\n            GOOGLE_NOTEBOOKLM: 'Google-NotebookLM',\n            GOOGLE_OTHER: 'GoogleOther',\n            GOOGLE_OTHER_IMAGE: 'GoogleOther-Image',\n            GOOGLE_OTHER_VIDEO: 'GoogleOther-Video',\n            GOOGLE_SAFETY: 'Google-Safety',\n            GOOGLE_STOREBOT: 'Storebot-Google',\n            HIVE_IMAGESIFTBOT: 'ImagesiftBot',\n            HUAWEI_PANGUBOT: 'PanguBot',\n            HUAWEI_PETALBOT: 'PetalBot',\n            HUGGINGFACE_BOT: 'HuggingFace-Bot',\n            HUNTER_VELENPUBLICWEBCRAWLER: 'VelenPublicWebCrawler',\n            IA_ARCHIVER: 'ia_archiver',\n            IASK_BOT: 'iAskBot',\n            KAGI_BOT: 'Kagibot',\n            KANGAROO_BOT: 'Kangaroo Bot',\n            LINE_SPIDER: 'Linespider',\n            LINKEDIN_BOT: 'LinkedInBot',\n            MAGPIE_CRAWLER: 'magpie-crawler',\n            MARGINALIA: 'marginalia',\n            META_EXTERNALAGENT: 'meta-externalagent',\n            META_FACEBOOKBOT: 'FacebookBot',\n            META_FACEBOOKCATALOG: 'facebookcatalog',\n            META_FACEBOOKEXTERNALHIT: 'facebookexternalhit',\n            MAJESTIC_MJ12BOT: 'MJ12bot',\n            MICROSOFT_BINGBOT: 'Bingbot',\n            MICROSOFT_MSNBOT: 'msnbot',\n            MICROSOFT_ADIDXBOT: 'adidxbot',\n            MOJEEK_BOT: 'MojeekBot',\n            MOZ_DOTBOT: 'DotBot',\n            ONCRAWL: 'OnCrawl',\n            ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot',\n            OPENAI_GPTBOT: 'GPTBot',\n            OPENAI_SEARCH_BOT: 'OAI-SearchBot',\n            PERPLEXITY_BOT: 'PerplexityBot',\n            QIHOO_360_SPIDER: '360Spider',\n            QWANT_BOT: 'Qwantbot',\n            QWANT_BOT_NEWS: 'Qwantbot-news',\n            REPLICATE_BOT: 'Replicate-Bot',\n            RUNPOD_BOT: 'RunPod-Bot',\n            SB_INTUITIONS_BOT: 'SBIntuitionsBot',\n            SEEKPORT_BOT: 'SeekportBot',\n            SEMRUSH_BOT: 'SemrushBot',\n            SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA',\n            SEMRUSH_BOT_CONTENTSHAKE: 'SemrushBot-OCOB',\n            SEMRUSH_BOT_SEO_CHECKER: 'SemrushBot-SI',\n            SEMRUSH_BOT_SWA: 'SemrushBot-SWA',\n            SEZNAM_BOT: 'SeznamBot',\n            SITEIMPROVE: 'Siteimprove',\n            SOGOU_PIC_SPIDER: 'Sogou Pic Spider',\n            SOGOU_WEB_SPIDER: 'Sogou web spider',\n            STARTPAGE: 'Startpage',\n            SURLY_BOT: 'SurdotlyBot',\n            TIMPI_BOT: 'Timpibot',\n            TOGETHER_BOT: 'Together-Bot',\n            TURNITIN_BOT: 'TurnitinBot',\n            TWIN_AGENT: 'TwinAgent',\n            VERCEL_V0BOT: 'v0bot',\n            WEBZIO: 'webzio',\n            WEBZIO_EXTENDED: 'Webzio-Extended',\n            WEBZIO_OMGILI: 'omgili',\n            WEBZIO_OMGILI_BOT: 'omgilibot',\n            XAI_BOT: 'xAI-Bot',\n            YAHOO_JAPAN: 'Y!J-BRW',\n            YAHOO_SLURP: 'Yahoo! Slurp',\n            YANDEX_ACCESSIBILITY_BOT: 'YandexAccessibilityBot',\n            YANDEX_ADDITIONAL_BOT: 'YandexAdditionalBot',\n            YANDEX_ADNET: 'YandexAdNet',\n            YANDEX_BLOGS: 'YandexBlogs',\n            YANDEX_BOT: 'YandexBot',\n            YANDEX_BOT_MIRRORDETECTOR: 'YandexBot MirrorDetector',\n            YANDEX_COMBOT: 'YandexComBot',\n            YANDEX_FAVICONS: 'YandexFavicons',\n            YANDEX_IMAGE_RESIZER: 'YandexImageResizer',\n            YANDEX_IMAGES: 'YandexImages',\n            YANDEX_MARKET: 'YandexMarket',\n            YANDEX_MEDIA: 'YandexMedia',\n            YANDEX_METRIKA: 'YandexMetrika',\n            YANDEX_MOBILE_BOT: 'YandexMobileBot',\n            YANDEX_MOBILE_SCREENSHOT_BOT: 'YandexMobileScreenShotBot',\n            YANDEX_NEWS: 'YandexNews',\n            YANDEX_ONTODB: 'YandexOntoDB',\n            YANDEX_ONTODB_API: 'YandexOntoDBAPI',\n            YANDEX_PARTNER: 'YandexPartner',\n            YANDEX_RCA: 'YandexRCA',\n            YANDEX_RENDERRESOURCES_BOT: 'YandexRenderResourcesBot',\n            YANDEX_SCREENSHOT_BOT: 'YandexScreenshotBot',\n            YANDEX_SPRAV_BOT: 'YandexSpravBot',\n            YANDEX_TRACKER: 'YandexTracker',\n            YANDEX_VERTICALS: 'YandexVerticals',\n            YANDEX_VERTIS: 'YandexVertis',\n            YANDEX_VIDEO: 'YandexVideo',\n            YANDEX_VIDEO_PARSER: 'YandexVideoParser',\n            YANDEX_WEBMASTER: 'YandexWebmaster',\n            YEP_BOT: 'YepBot',\n            YETI: 'Yeti',\n            YISOU_SPIDER: 'YisouSpider',\n            YOU_BOT: 'YouBot',\n            ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',\n            ZUM_BOT: 'ZumBot'\n        },\n        Email: {\n            AIRMAIL: 'Airmail',\n            ALPINE: 'Alpine',\n            ANDROID_MAIL: 'Android',\n            APPLE_MAIL: 'Mail',\n            AQUA_MAIL: 'AquaMail',\n            BALSA: 'Balsa',\n            BARCA: 'Barca',\n            BLUEMAIL: 'BlueMail',\n            CANARY: 'Canary',\n            CLAWS_MAIL: 'Claws Mail',\n            DAUM_MAIL: 'DaumMail',\n            EM_CLIENT: 'eM Client',\n            EUDORA: 'Eudora',\n            EVOLUTION: 'Evolution',\n            FAIR_EMAIL: 'FairEmail',\n            FOXMAIL: 'Foxmail',\n            GEARY: 'Geary',\n            GNUS: 'Gnus',\n            HORDE_IMP: 'Horde::IMP',\n            IBM_NOTES: 'Lotus-Notes',\n            INCREDIMAIL: 'IncrediMail',\n            K9_MAIL: 'K-9 Mail',\n            KMAIL: 'KMail',\n            KMAIL2: 'kmail2',\n            KONTACT: 'Kontact',\n            MAILBIRD: 'Mailbird',\n            MAILMATE: 'MailMate',\n            MAILSPRING: 'Mailspring',\n            MICROSOFT_OUTLOOK: 'Microsoft Outlook',\n            MICROSOFT_OUTLOOK_MAC: 'MacOutlook',\n            MUTT: 'Mutt',\n            NAVER_MAILAPP: 'NaverMailApp',\n            NEWTON: 'Newton',\n            NINE: 'Nine',\n            NYLAS_MAIL: 'NylasMail',\n            OUTLOOK_EXPRESS: 'Outlook-Express',\n            PEGASUS_MAIL: 'Pegasus Mail',\n            POCOMAIL: 'PocoMail',\n            POLYMAIL: 'Polymail',\n            POSTBOX: 'Postbox',\n            PROTON_MAIL: 'ProtonMail',\n            PROTON_MAIL_BRIDGE: 'ProtonMail Bridge',\n            QUALA_MAIL: 'Quala',\n            R2MAIL2: 'R2Mail2',\n            RAINLOOP: 'RainLoop',\n            ROUNDCUBE: 'Roundcube Webmail',\n            SAMSUNG_EMAIL: 'SamsungEmail',\n            SPARK_MAIL: 'SparkDesktop',\n            SPARROW: 'Sparrow',\n            SPICEBIRD: 'Spicebird',\n            SQUIRRELMAIL: 'SquirrelMail',\n            SYLPHEED: 'Sylpheed',\n            THE_BAT: 'The Bat!',\n            THUNDERBIRD: 'Thunderbird',\n            TROJITA: 'Trojita',\n            TURNPIKE: 'Turnpike',\n            TUTANOTA: 'tutanota-desktop',\n            WANDERLUST: 'Wanderlust',\n            WINDOWS_LIVE_MAIL: 'Windows-Live-Mail',\n            YAHOO_MAIL: 'Yahoo Mail',\n            YAHOO_MAIL_IOS: 'Yahoo Mail',\n            ZIMBRA: 'Zimbra',\n            ZOHO_MAIL: 'ZohoMail-Desktop'\n        },\n        Fetcher: {\n            AHREFS_SITEAUDIT: 'AhrefsSiteAudit',\n            AMAZON_NOVA_ACT: 'NovaAct',\n            ANTHROPIC_CLAUDE_USER: 'Claude-User',\n            ASANA: 'Asana',\n            BETTER_UPTIME_BOT: 'Better Uptime Bot',\n            BITLY_BOT: 'bitlybot',\n            BLUESKY: 'Bluesky',\n            BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',\n            COHERE_AI: 'Cohere-AI',\n            DISCORD_BOT: 'Discordbot',\n            DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',\n            FLIPBOARD_PROXY: 'FlipboardProxy',\n            GOOGLE_CHROME_LIGHTHOUSE: 'Lighthouse',\n            GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',\n            GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research',\n            GOOGLE_IMAGEPROXY: 'GoogleImageProxy',\n            GOOGLE_PAGERENDERER: 'Google-PageRenderer',\n            GOOGLE_READ_ALOUD: 'Google-Read-Aloud',\n            GOOGLE_PRODUCER: 'GoogleProducer',\n            GOOGLE_SITE_VERIFICATION: 'Google-Site-Verification',\n            HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',\n            IFRAMELY: 'Iframely',\n            KAKAOTALK_SCRAP: 'kakaotalk-scrap',\n            KEYBASE_BOT: 'KeybaseBot',\n            META_EXTERNALFETCHER: 'meta-externalfetcher',\n            META_WHATSAPP: 'WhatsApp',\n            MICROSOFT_BINGPREVIEW: 'BingPreview',\n            MICROSOFT_PREVIEW: 'MicrosoftPreview',\n            MISTRALAI_USER: 'MistralAI-User',\n            NAVER_BLUENO: 'Blueno',\n            ONCRAWL_ROGERBOT: 'rogerbot',\n            OPENAI_CHATGPT_USER: 'ChatGPT-User',\n            PERPLEXITY_USER: 'Perplexity-User',\n            PINTEREST_BOT: 'Pinterestbot',\n            SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',\n            SLACK_BOT: 'Slackbot',\n            SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',\n            SLACK_IMGPROXY: 'Slack-ImgProxy',\n            SNAP_URL_PREVIEW: 'Snap URL Preview',\n            SKYPE_URIPREVIEW: 'SkypeUriPreview',\n            TELEGRAM_BOT: 'TelegramBot',\n            UPTIMEROBOT: 'UptimeRobot',\n            VERCEL_FAVICON_BOT: 'vercel-favicon-bot',\n            VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',\n            VERCEL_BOT: 'Vercelbot',\n            VERCEL_FLAGS: 'vercelflags',\n            VERCEL_TRACING: 'verceltracing',\n            X_TWITTERBOT: 'Twitterbot',\n            YANDEX_CALENDAR: 'YandexCalendar',\n            YANDEX_DIRECT: 'YandexDirect',\n            YANDEX_DIRECTDYN: 'YandexDirectDyn',\n            YANDEX_DIRECTFETCHER: 'YaDirectFetcher',\n            YANDEX_FORDOMAIN: 'YandexForDomain',\n            YANDEX_PAGECHECKER: 'YandexPagechecker',\n            YANDEX_SEARCHSHOP: 'YandexSearchShop',\n            YANDEX_SITELINKS: 'YandexSitelinks',\n            YANDEX_USERPROXY: 'YandexUserproxy',\n            ZOOMINFO_BOT: 'Zoombot'\n        },\n        InApp: {\n            DISCORD: 'Discord',\n            EVERNOTE: 'Evernote',\n            FIGMA: 'Figma',\n            FLIPBOARD: 'Flipboard',\n            MATTERMOST: 'Mattermost',\n            TEAMS: 'Teams',\n            NOTION: 'Notion',\n            POSTMAN: 'Postman',\n            RAMBOX: 'Rambox',\n            ROCKETCHAT: 'Rocket.Chat',\n            SLACK: 'Slack',\n            TIKTOK_LITE: 'TikTok Lite',\n            VSCODE: 'VS Code',\n            YAHOO_JAPAN: 'Yahoo! Japan'\n        },\n        Library: {\n            ADOBE_AIR: 'AdobeAIR',\n            AIOHTTP: 'aiohttp',\n            APACHE_HTTPCLIENT: 'Apache-HttpClient',\n            AXIOS: 'axios',\n            BUN: 'Bun',\n            DART: 'Dart',\n            DENO: 'Deno',\n            GO_HTTP_CLIENT: 'go-http-client',\n            GOT: 'got',\n            GUZZLEHTTP: 'GuzzleHttp',\n            HACKNEY: 'hackney',\n            HTTP_RB: 'http.rb',\n            JAVA: 'Java',\n            JAVA_HTTPCLIENT: 'Java-http-client',\n            JETTY: 'Jetty',\n            JSDOM: 'jsdom',\n            LIBWWW_PERL: 'libwww-perl',\n            LUA_RESTY_HTTP: 'lua-resty-http',\n            NEEDLE: 'Needle',\n            NUTCH: 'Nutch',\n            NODE_FETCH: 'node-fetch',\n            NODE_JS: 'Node.js',\n            NODE_SUPERAGENT: 'node-superagent',\n            OKHTTP: 'OkHttp',\n            OCAML_COHTTP: 'ocaml-cohttp',\n            PHP_SOAP: 'PHP-SOAP',\n            POSTMAN_RUNTIME: 'PostmanRuntime',\n            PYTHON_HTTPX: 'python-httpx',\n            PYTHON_URLLIB: 'python-urllib',\n            PYTHON_URLLIB3: 'python-urllib3',\n            PYTHON_REQUESTS: 'python-requests',\n            REST_CLIENT: 'rest-client',\n            SCRAPY: 'Scrapy',\n            UNDICI: 'undici'\n        }\n    },\n    DeviceVendor: {\n        Vehicle: {\n            BMW: 'BMW',\n            BYD: 'BYD',\n            JEEP: 'Jeep',\n            RIVIAN: 'Rivian',\n            TESLA: 'Tesla',\n            VOLVO: 'Volvo'\n        }\n    }\n}>;\n\n"
  },
  {
    "path": "src/enums/ua-parser-enums.js",
    "content": "///////////////////////////////////////////////\n/*  Enums for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst BrowserName = Object.freeze({\n    '115': '115',\n    '2345': '2345',\n    '360': '360',\n    ALIPAY: 'Alipay',\n    ALOHA: 'Aloha',\n    AMAYA: 'Amaya',\n    ANDROID: 'Android Browser',\n    ARORA: 'Arora',\n    ATLAS: 'Atlas',\n    AVANT: 'Avant',\n    AVAST: 'Avast Secure Browser',\n    AVG: 'AVG Secure Browser',\n    AVIRA: 'Avira Secure Browser',\n    BAIDU: 'Baidu Browser',\n    BASILISK: 'Basilisk',\n    BING: 'Bing',\n    BLAZER: 'Blazer',\n    BOLT: 'Bolt',\n    BOWSER: 'Bowser',\n    BRAVE: 'Brave',\n    CAMINO: 'Camino',\n    CHIMERA: 'Chimera',\n    CHROME: 'Chrome',\n    CHROME_HEADLESS: 'Chrome Headless',\n    CHROME_MOBILE: 'Mobile Chrome',\n    CHROME_WEBVIEW: 'Chrome WebView',\n    CHROMIUM: 'Chromium',\n    COBALT: 'Cobalt',\n    COC_COC: 'Coc Coc',\n    CONKEROR: 'Conkeror',\n    DAUM: 'Daum',\n    DILLO: 'Dillo',\n    DOLPHIN: 'Dolphin',\n    DOOBLE: 'Dooble',\n    DORIS: 'Doris',\n    DRAGON: 'Dragon',\n    DUCKDUCKGO: 'DuckDuckGo',\n    ECOSIA: 'Ecosia',\n    EDGE: 'Edge',\n    EDGE_WEBVIEW: 'Edge WebView',\n    EDGE_WEBVIEW2: 'Edge WebView2',\n    EPIPHANY: 'Epiphany',\n    FACEBOOK: 'Facebook',\n    FALKON: 'Falkon',\n    FIREBIRD: 'Firebird',\n    FIREFOX: 'Firefox',\n    FIREFOX_FOCUS: 'Firefox Focus',\n    FIREFOX_MOBILE: 'Mobile Firefox',\n    FIREFOX_REALITY: 'Firefox Reality',\n    FENNEC: 'Fennec',\n    FLOCK: 'Flock',\n    FLOW: 'Flow',\n    GO: 'GoBrowser',\n    GOOGLE_SEARCH: 'GSA',\n    HELIO: 'Helio',\n    HEYTAP: 'HeyTap',\n    HIBROWSER: 'HiBrowser',\n    HONOR: 'Honor',\n    HUAWEI: 'Huawei Browser',\n    ICAB: 'iCab',\n    ICE: 'ICE Browser',\n    ICEAPE: 'IceApe',\n    ICECAT: 'IceCat',\n    ICEDRAGON: 'IceDragon',\n    ICEWEASEL: 'IceWeasel',\n    IE: 'IE',\n    INSTAGRAM: 'Instagram',\n    IRIDIUM: 'Iridium',\n    IRON: 'Iron',\n    JASMINE: 'Jasmine',\n    KONQUEROR: 'Konqueror',\n    KAKAO: 'KakaoTalk',\n    KHTML: 'KHTML',\n    K_MELEON: 'K-Meleon',\n    KLAR: 'Klar',\n    KLARNA: 'Klarna',\n    KINDLE: 'Kindle',\n    LENOVO: 'Smart Lenovo Browser',\n    LADYBIRD: 'Ladybird',\n    LG: 'LG Browser',\n    LIBREWOLF: 'LibreWolf',\n    LIEBAO: 'LBBROWSER',\n    LIGHTHOUSE: 'Lighthouse',\n    LINE: 'Line',\n    LINKEDIN: 'LinkedIn',\n    LINKS: 'Links',\n    LUAKIT: 'Luakit',\n    LUNASCAPE: 'Lunascape',\n    LYNX: 'Lynx',\n    MAEMO: 'Maemo Browser',\n    MAXTHON: 'Maxthon',\n    MIDORI: 'Midori',\n    MINIMO: 'Minimo',\n    MIUI: 'MIUI Browser',\n    MOZILLA: 'Mozilla',\n    MOSAIC: 'Mosaic',\n    NAVER: 'Naver',\n    NETFRONT: 'NetFront',\n    NETSCAPE: 'Netscape',\n    NETSURF: 'Netsurf',\n    NOKIA: 'Nokia Browser',\n    NORTON: 'Norton Private Browser',\n    OBIGO: 'Obigo',\n    OCULUS: 'Oculus Browser',\n    OMNIWEB: 'OmniWeb',\n    OPERA: 'Opera',\n    OPERA_COAST: 'Opera Coast',\n    OPERA_GX: 'Opera GX',\n    OPERA_MINI: 'Opera Mini',\n    OPERA_MOBI: 'Opera Mobi',\n    OPERA_NEON: 'Opera Neon',\n    OPERA_TABLET: 'Opera Tablet',\n    OPERA_TOUCH: 'Opera Touch',\n    OTTER: 'Otter',\n    OVI: 'OviBrowser',\n    PALEMOON: 'PaleMoon',\n    PHANTOMJS: 'PhantomJS',\n    PHOENIX: 'Phoenix',\n    PICOBROWSER: 'Pico Browser',\n    POLARIS: 'Polaris',\n    PUFFIN: 'Puffin',\n    QQ: 'QQBrowser',\n    QQ_LITE: 'QQBrowserLite',\n    QUARK: 'Quark',\n    QUPZILLA: 'QupZilla',\n    QUTEBROWSER: 'qutebrowser',\n    QWANT: 'Qwant',\n    REKONQ: 'rekonq',\n    ROCKMELT: 'Rockmelt',\n    SAFARI: 'Safari',\n    SAFARI_MOBILE: 'Mobile Safari',\n    SAILFISH: 'Sailfish Browser',\n    SAMSUNG: 'Samsung Internet',\n    SEAMONKEY: 'SeaMonkey',\n    SILK: 'Silk',\n    SKYFIRE: 'Skyfire',\n    SLEIPNIR: 'Sleipnir',\n    SLIMBOAT: 'SlimBoat',\n    SLIMBROWSER: 'SlimBrowser',\n    SLIMJET: 'Slimjet',\n    SNAPCHAT: 'Snapchat',\n    SOGOU_EXPLORER: 'Sogou Explorer',\n    SOGOU_MOBILE: 'Sogou Mobile',\n    STEAM: 'Steam',\n    SURF: 'Surf',\n    SWIFTFOX: 'Swiftfox',\n    TESLA: 'Tesla',\n    TIKTOK: 'TikTok',\n    TIZEN: 'Tizen Browser',\n    TWITTER: 'Twitter',\n    UC: 'UCBrowser',\n    UP: 'UP.Browser',\n    VIVALDI: 'Vivaldi',\n    VIVO: 'Vivo Browser',\n    W3M: 'w3m',\n    WATERFOX: 'Waterfox',\n    WEBKIT: 'WebKit',\n    WECHAT: 'WeChat',\n    WEIBO: 'Weibo',\n    WHALE: 'Whale',\n    WOLVIC: 'Wolvic',\n    YANDEX: 'Yandex',\n    ZALO: 'Zalo'\n\n    // TODO : test!\n});\n/**\n * @deprecated Use `BrowserName` instead\n */\nconst Browser = BrowserName;\n\nconst BrowserType = Object.freeze({\n    CRAWLER: 'crawler',\n    CLI: 'cli',\n    EMAIL: 'email',\n    FETCHER: 'fetcher',\n    INAPP: 'inapp',\n    MEDIAPLAYER: 'mediaplayer',\n    LIBRARY: 'library'\n});\n\nconst CPUArch = Object.freeze({\n    '68K': '68k',\n    ALPHA: 'alpha',\n    ARM : 'arm',\n    ARM_64: 'arm64',\n    ARM_HF: 'armhf',\n    AVR: 'avr',\n    AVR_32: 'avr32',\n    IA64: 'ia64',\n    IRIX: 'irix',\n    IRIX_64: 'irix64',\n    MIPS: 'mips',\n    MIPS_64: 'mips64',\n    PA_RISC: 'pa-risc',\n    PPC: 'ppc',\n    SPARC: 'sparc',\n    SPARC_64: 'sparc64',\n    X86: 'ia32',\n    X86_64: 'amd64'\n});\n/**\n * @deprecated Use `CPUArch` instead\n */\nconst CPU = CPUArch;\n\nconst DeviceType = Object.freeze({\n    CONSOLE: 'console',\n    EMBEDDED: 'embedded',\n    MOBILE: 'mobile',\n    SMARTTV: 'smarttv',\n    TABLET: 'tablet',\n    WEARABLE: 'wearable',\n    XR: 'xr',\n    /**\n     * @deprecated UAParser doesn't support `desktop` type, see https://docs.uaparser.dev/info/device/type\n     */\n    DESKTOP: 'desktop'\n});\n/**\n * @deprecated Use `DeviceType` instead\n */\nconst Device = DeviceType;\n\nconst DeviceVendor = Object.freeze({\n    ACER: 'Acer',\n    ADVAN: 'Advan',\n    ALCATEL: 'Alcatel',\n    AMAZON: 'Amazon',\n    ANBERNIC: 'Anbernic',\n    APPLE: 'Apple',\n    ARCHOS: 'Archos',\n    ASUS: 'ASUS',\n    ATT: 'AT&T',\n    BENQ: 'BenQ',\n    BLACKBERRY: 'BlackBerry',\n    BLACKVIEW: 'Blackview',\n    BLU: 'BLU',\n    CAT: 'Cat',\n    COOLPAD: 'Coolpad',\n    CUBOT: 'CUBOT',\n    DELL: 'Dell',\n    ENERGIZER: 'Energizer',\n    ESSENTIAL: 'Essential',\n    FACEBOOK: 'Facebook',\n    FAIRPHONE: 'Fairphone',\n    GEEKSPHONE: 'GeeksPhone',\n    GENERIC: 'Generic',\n    GOOGLE: 'Google',\n    HISENSE: 'Hisense',\n    HMD: 'HMD',\n    HP: 'HP',\n    HTC: 'HTC',\n    HUAWEI: 'Huawei',\n    IMO: 'IMO',\n    INFINIX: 'Infinix',\n    ITEL: 'itel',\n    JOLLA: 'Jolla',\n    KOBO: 'Kobo',\n    LAVA: 'Lava',\n    LENOVO: 'Lenovo',\n    LG: 'LG',\n    LOGITECH: 'Logitech',\n    MEIZU: 'Meizu',\n    MICROMAX: 'Micromax',\n    MICROSOFT: 'Microsoft',\n    MOTOROLA: 'Motorola',\n    NEXIAN: 'Nexian',\n    NINTENDO: 'Nintendo',\n    NOKIA: 'Nokia',\n    NOTHING: 'Nothing',\n    NVIDIA: 'Nvidia',\n    ONEPLUS: 'OnePlus',\n    OPPO: 'OPPO',\n    OUYA: 'Ouya',\n    PALM: 'Palm',\n    PANASONIC: 'Panasonic',\n    PEBBLE: 'Pebble',\n    PHILIPS: 'Philips',\n    PICO: 'Pico',\n    POLYTRON: 'Polytron',\n    REALME: 'Realme',\n    RETROID: 'Retroid',\n    RIM: 'RIM',\n    ROKU: 'Roku',\n    SAMSUNG: 'Samsung',\n    SHARP: 'Sharp',\n    SIEMENS: 'Siemens',\n    SMARTFREN: 'Smartfren',\n    SONY: 'Sony',\n    SPRINT: 'Sprint',\n    TCL: 'TCL',\n    TECHNISAT: 'TechniSAT',\n    TECNO: 'TECNO',\n    TESLA: 'Tesla',\n    T_MOBILE: 'T-Mobile',\n    ULEFONE: 'Ulefone',\n    VALVE: 'Valve',\n    VIVO: 'Vivo',\n    VIZIO: 'Vizio',\n    VODAFONE: 'Vodafone',\n    WIKO: 'Wiko',\n    XBOX: 'Xbox',\n    XIAOMI: 'Xiaomi',\n    ZEBRA: 'Zebra',\n    ZTE: 'ZTE',\n\n    // TODO : test!\n});\n/**\n * @deprecated Use `DeviceVendor` instead\n */\nconst Vendor = DeviceVendor;\n\nconst EngineName = Object.freeze({\n    AMAYA: 'Amaya',\n    ARKWEB: 'ArkWeb',\n    BLINK: 'Blink',\n    DILLO: 'Dillo',\n    EDGEHTML: 'EdgeHTML',\n    FLOW: 'Flow',\n    GECKO: 'Gecko',\n    GOANNA: 'Goanna',\n    ICAB: 'iCab',\n    KHTML: 'KHTML',\n    LIBWEB: 'LibWeb',\n    LINKS: 'Links',\n    LYNX: 'Lynx',\n    NETFRONT: 'NetFront',\n    NETSURF: 'NetSurf',\n    PRESTO: 'Presto',\n    SERVO: 'Servo',\n    TASMAN: 'Tasman',\n    TRIDENT: 'Trident',\n    W3M: 'w3m',\n    WEBKIT: 'WebKit'\n});\n/**\n * @deprecated Use `EngineName` instead\n */\nconst Engine = EngineName;\n\nconst OSName = Object.freeze({\n    AIX: 'AIX',\n    AMIGA_OS: 'Amiga OS',\n    ANDROID: 'Android',\n    ANDROID_X86: 'Android-x86',\n    ARCAOS: 'ArcaOS',\n    ARCH: 'Arch',\n    BADA: 'Bada',\n    BEOS: 'BeOS',\n    BLACKBERRY: 'BlackBerry',\n    CENTOS: 'CentOS',\n    CHROME_OS: 'Chrome OS',\n    CHROMECAST: 'Chromecast',\n    CHROMECAST_ANDROID: 'Chromecast Android',\n    CHROMECAST_FUCHSIA: 'Chromecast Fuchsia',\n    CHROMECAST_LINUX: 'Chromecast Linux',\n    CHROMECAST_SMARTSPEAKER: 'Chromecast SmartSpeaker',\n    CONTIKI: 'Contiki',\n    DEBIAN: 'Debian',\n    DEEPIN: 'Deepin',\n    DRAGONFLY: 'DragonFly',\n    ELEMENTARY_OS: 'elementary OS',\n    FEDORA: 'Fedora',\n    FIREFOX_OS: 'Firefox OS',\n    FREEBSD: 'FreeBSD',\n    FUCHSIA: 'Fuchsia',\n    GENTOO: 'Gentoo',\n    GHOSTBSD: 'GhostBSD',\n    GNU: 'GNU',\n    HAIKU: 'Haiku',\n    HARMONYOS: 'HarmonyOS',\n    HP_UX: 'HP-UX',\n    HURD: 'Hurd',\n    IOS: 'iOS',\n    JOLI: 'Joli',\n    KAIOS: 'KaiOS',\n    KNOPPIX: 'Knoppix',\n    KUBUNTU: 'Kubuntu',\n    LINPUS: 'Linpus',\n    LINSPIRE: 'Linspire',\n    LINUX: 'Linux',\n    MACOS: 'macOS',\n    MAEMO: 'Maemo',\n    MAGEIA: 'Mageia',\n    MANDRIVA: 'Mandriva',\n    MANJARO: 'Manjaro',\n    MEEGO: 'MeeGo',\n    MINIX: 'Minix',\n    MINT: 'Mint',\n    MORPH_OS: 'Morph OS',\n    NETBSD: 'NetBSD',\n    NETRANGE: 'NetRange',\n    NETTV: 'NetTV',\n    NINTENDO: 'Nintendo',\n    OPENHARMONY: 'OpenHarmony',\n    OPENBSD: 'OpenBSD',\n    OPENVMS: 'OpenVMS',\n    OS2: 'OS/2',\n    PALM: 'Palm',\n    PC_BSD: 'PC-BSD',\n    PCLINUXOS: 'PCLinuxOS',\n    PICO: 'Pico',\n    PLAN9: 'Plan9',\n    PLAYSTATION: 'PlayStation',\n    QNX: 'QNX',\n    RASPBIAN: 'Raspbian',\n    REDHAT: 'RedHat',\n    RIM_TABLET_OS: 'RIM Tablet OS',\n    RISC_OS: 'RISC OS',\n    SABAYON: 'Sabayon',\n    SAILFISH: 'Sailfish',\n    SERENITYOS: 'SerenityOS',\n    SERIES40: 'Series40',\n    SLACKWARE: 'Slackware',\n    SOLARIS: 'Solaris',\n    SUSE: 'SUSE',\n    SYMBIAN: 'Symbian',\n    TIZEN: 'Tizen',\n    UBUNTU: 'Ubuntu',\n    UBUNTU_TOUCH: 'Ubuntu Touch',\n    UNIX: 'Unix',\n    VECTORLINUX: 'VectorLinux',\n    VEGA_OS: 'Vega OS',\n    WATCHOS: 'watchOS',\n    WEBOS: 'WebOS',\n    WINDOWS: 'Windows',\n    WINDOWS_CE: 'Windows CE',\n    WINDOWS_IOT: 'Windows IoT',\n    WINDOWS_MOBILE: 'Windows Mobile',\n    WINDOWS_PHONE: 'Windows Phone',\n    WINDOWS_RT: 'Windows RT',\n    XBOX: 'Xbox',\n    XUBUNTU: 'Xubuntu',\n    ZENWALK: 'Zenwalk'\n\n    // TODO : test!\n});\n/**\n * @deprecated Use `OSName` instead\n */\nconst OS = OSName;\n\n/*////////////////////////////////\n * Enums for Extensions submodule\n *///////////////////////////////\n\nconst Extension = Object.freeze({\n    BrowserName: {\n        CLI: {\n            CURL: 'curl',\n            ELINKS: 'ELinks',\n            HTTPIE: 'HTTPie',\n            LYNX: 'Lynx',\n            POWERSHELL: 'PowerShell',\n            WGET: 'Wget'\n        },\n        Crawler: {\n            AHREFS_BOT: 'AhrefsBot',\n            AI2_BOT: 'AI2Bot',\n            AIHIT_BOT: 'aiHitBot',\n            ALGOLIA_CRAWLER: 'Algolia Crawler',\n            APPLE_BOT: 'Applebot',\n            APPLE_BOT_EXTENDED: 'Applebot-Extended',\n            ASK_TEOMA: 'Teoma',\n            AMAZON_BOT: 'Amazonbot',\n            AMAZON_CONTXBOT: 'contxbot',\n            ANTHROPIC_AI: 'anthropic-ai',\n            ANTHROPIC_CLAUDE_BOT: 'ClaudeBot',\n            ANTHROPIC_CLAUDE_SEARCHBOT: 'Claude-SearchBot',\n            ANTHROPIC_CLAUDE_WEB: 'Claude-Web',\n            ARCHIVEORG_BOT: 'archive.org_bot',\n            ATLASSIAN_BOT: 'atlassian-bot',\n            AUDISTO_CRAWLER: 'Audisto Crawler',\n            AWARIO_BOT: 'AwarioBot',\n            AWARIO_SMARTBOT: 'AwarioSmartBot',\n            AWARIO_RSSBOT: 'AwarioRssBot',\n            BAIDU_ADS: 'Baidu-ADS',\n            BAIDU_SPIDER: 'Baiduspider',\n            BAIDU_SPIDER_ADS: 'Baiduspider-ads',\n            BAIDU_SPIDER_CPRO: 'Baiduspider-cpro',\n            BAIDU_SPIDER_FAVO: 'Baiduspider-favo',\n            BAIDU_SPIDER_IMAGE: 'Baiduspider-image',\n            BAIDU_SPIDER_NEWS: 'Baiduspider-news',\n            BAIDU_SPIDER_RENDER: 'Baiduspider-render',\n            BAIDU_SPIDER_VIDEO: 'Baiduspider-video',\n            BLEX_BOT: 'BLEXBot',\n            BOTIFY: 'botify',\n            BRAVE_BOT: 'Bravebot',\n            BRIGHTEDGE_CRAWLER: 'BrightEdge Crawler',\n            BYTEDANCE_BYTESPIDER: 'Bytespider',\n            BYTEDANCE_TIKTOKSPIDER: 'TikTokSpider',\n            CLOUDFLARE_AUTORAG: 'Cloudflare-AutoRAG',\n            COMMON_CRAWL_CCBOT: 'CCBot',\n            COCCOC_BOT_WEB: 'coccocbot-web',\n            COCCOC_BOT_IMAGE: 'coccocbot-image',\n            COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler',\n            COMSCORE_PROXIMIC: 'proximic',\n            COTOYOGI: 'Cotoyogi',\n            COVEO_BOT: 'Coveobot',\n            CRITEO_BOT: 'CriteoBot',\n            DATAFORSEO_BOT: 'DataForSeoBot',\n            DAUM: 'Daum',\n            DAUM_DAUMOA: 'Daumoa',\n            DAUM_DAUMOA_IMAGE: 'Daumoa-image',\n            DEEPSEEK_BOT: 'DeepSeekBot',\n            DIFFBOT: 'Diffbot',\n            DUCKDUCKGO_BOT: 'DuckDuckBot',\n            DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',\n            ELASTIC: 'Elastic',\n            ELASTIC_SWIFTYPE_BOT: 'Swiftbot',\n            EXALEAD_EXABOT: 'Exabot',\n            FIRECRAWL_AGENT: 'FirecrawlAgent',\n            FREESPOKE: 'Freespoke',\n            GOOGLE_ADSBOT: 'AdsBot-Google',\n            GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile',\n            GOOGLE_ADSENSE: 'AdSense',\n            GOOGLE_APIS: 'APIs-Google',\n            GOOGLE_BOT: 'Googlebot',\n            GOOGLE_BOT_IMAGE: 'Googlebot-Image',\n            GOOGLE_BOT_NEWS: 'Googlebot-News',\n            GOOGLE_BOT_VIDEO: 'Googlebot-Video',\n            GOOGLE_CLOUDVERTEXBOT: 'Google-CloudVertexBot',\n            GOOGLE_EXTENDED: 'Google-Extended',\n            GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool',\n            GOOGLE_NOTEBOOKLM: 'Google-NotebookLM',\n            GOOGLE_OTHER: 'GoogleOther',\n            GOOGLE_OTHER_IMAGE: 'GoogleOther-Image',\n            GOOGLE_OTHER_VIDEO: 'GoogleOther-Video',\n            GOOGLE_SAFETY: 'Google-Safety',\n            GOOGLE_STOREBOT: 'Storebot-Google',\n            HEADLINE: 'Headline',\n            HIVE_IMAGESIFTBOT: 'ImagesiftBot',\n            HUAWEI_PANGUBOT: 'PanguBot',\n            HUAWEI_PETALBOT: 'PetalBot',\n            HUBSPOT_CRAWLER: 'HubSpot Crawler',\n            HUGGINGFACE_BOT: 'HuggingFace-Bot',\n            HUNTER_VELENPUBLICWEBCRAWLER: 'VelenPublicWebCrawler',\n            IA_ARCHIVER: 'ia_archiver',\n            IASK_BOT: 'iAskBot',\n            KAGI_BOT: 'Kagibot',\n            KANGAROO_BOT: 'Kangaroo Bot',\n            LINE_SPIDER: 'Linespider',\n            LINKEDIN_BOT: 'LinkedInBot',\n            MAGPIE_CRAWLER: 'magpie-crawler',\n            MARGINALIA: 'marginalia',\n            META_EXTERNALADS: 'meta-externalads',\n            META_EXTERNALAGENT: 'meta-externalagent',\n            META_FACEBOOKBOT: 'FacebookBot',\n            META_FACEBOOKCATALOG: 'facebookcatalog',\n            META_FACEBOOKEXTERNALHIT: 'facebookexternalhit',\n            META_WEBINDEXER: 'meta-webindexer',\n            MAJESTIC_MJ12BOT: 'MJ12bot',\n            MICROSOFT_BINGBOT: 'Bingbot',\n            MICROSOFT_MSNBOT: 'msnbot',\n            MICROSOFT_ADIDXBOT: 'adidxbot',\n            MOJEEK_BOT: 'MojeekBot',\n            MOZ_DOTBOT: 'DotBot',\n            ONCRAWL: 'OnCrawl',\n            ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot',\n            OPENAI_GPTBOT: 'GPTBot',\n            OPENAI_SEARCH_BOT: 'OAI-SearchBot',\n            PERPLEXITY_BOT: 'PerplexityBot',\n            QIHOO_360_SPIDER: '360Spider',\n            QWANT_BOT: 'Qwantbot',\n            QWANT_BOT_NEWS: 'Qwantbot-news',\n            REPLICATE_BOT: 'Replicate-Bot',\n            RUNPOD_BOT: 'RunPod-Bot',\n            SB_INTUITIONS_BOT: 'SBIntuitionsBot',\n            SEEKPORT_BOT: 'SeekportBot',\n            SEMRUSH_BOT: 'SemrushBot',\n            SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA',\n            SEMRUSH_BOT_CONTENTSHAKE: 'SemrushBot-OCOB',\n            SEMRUSH_BOT_SEO_CHECKER: 'SemrushBot-SI',\n            SEMRUSH_BOT_SWA: 'SemrushBot-SWA',\n            SEZNAM_BOT: 'SeznamBot',\n            SITEIMPROVE: 'Siteimprove',\n            SOGOU_PIC_SPIDER: 'Sogou Pic Spider',\n            SOGOU_WEB_SPIDER: 'Sogou web spider',\n            STARTPAGE: 'Startpage',\n            SURLY_BOT: 'SurdotlyBot',\n            TIMPI_BOT: 'Timpibot',\n            TOGETHER_BOT: 'Together-Bot',\n            TURNITIN_BOT: 'TurnitinBot',\n            TWIN_AGENT: 'TwinAgent',\n            VERCEL_V0BOT: 'v0bot',\n            WEBZIO: 'webzio',\n            WEBZIO_EXTENDED: 'Webzio-Extended',\n            WEBZIO_OMGILI: 'omgili',\n            WEBZIO_OMGILI_BOT: 'omgilibot',\n            XAI_BOT: 'xAI-Bot',\n            YACY_BOT: 'yacybot',\n            YAHOO_JAPAN: 'Y!J-BRW',\n            YAHOO_SLURP: 'Yahoo! Slurp',\n            YANDEX_ACCESSIBILITY_BOT: 'YandexAccessibilityBot',\n            YANDEX_ADDITIONAL_BOT: 'YandexAdditionalBot',\n            YANDEX_ADNET: 'YandexAdNet',\n            YANDEX_BLOGS: 'YandexBlogs',\n            YANDEX_BOT: 'YandexBot',\n            YANDEX_BOT_MIRRORDETECTOR: 'YandexBot MirrorDetector',\n            YANDEX_COMBOT: 'YandexComBot',\n            YANDEX_FAVICONS: 'YandexFavicons',\n            YANDEX_IMAGE_RESIZER: 'YandexImageResizer',\n            YANDEX_IMAGES: 'YandexImages',\n            YANDEX_MARKET: 'YandexMarket',\n            YANDEX_MEDIA: 'YandexMedia',\n            YANDEX_METRIKA: 'YandexMetrika',\n            YANDEX_MOBILE_BOT: 'YandexMobileBot',\n            YANDEX_MOBILE_SCREENSHOT_BOT: 'YandexMobileScreenShotBot',\n            YANDEX_NEWS: 'YandexNews',\n            YANDEX_ONTODB: 'YandexOntoDB',\n            YANDEX_ONTODB_API: 'YandexOntoDBAPI',\n            YANDEX_PARTNER: 'YandexPartner',\n            YANDEX_RCA: 'YandexRCA',\n            YANDEX_RENDERRESOURCES_BOT: 'YandexRenderResourcesBot',\n            YANDEX_SCREENSHOT_BOT: 'YandexScreenshotBot',\n            YANDEX_SPRAV_BOT: 'YandexSpravBot',\n            YANDEX_TRACKER: 'YandexTracker',\n            YANDEX_VERTICALS: 'YandexVerticals',\n            YANDEX_VERTIS: 'YandexVertis',\n            YANDEX_VIDEO: 'YandexVideo',\n            YANDEX_VIDEO_PARSER: 'YandexVideoParser',\n            YANDEX_WEBMASTER: 'YandexWebmaster',\n            YEP_BOT: 'YepBot',\n            YETI: 'Yeti',\n            YISOU_SPIDER: 'YisouSpider',\n            YOU_BOT: 'YouBot',\n            ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',\n            ZUM_BOT: 'ZumBot'\n        },\n        Email: {\n            AIRMAIL: 'Airmail',\n            ALPINE: 'Alpine',\n            ANDROID_MAIL: 'Android',\n            APPLE_MAIL: 'Mail',\n            AQUA_MAIL: 'AquaMail',\n            BALSA: 'Balsa',\n            BARCA: 'Barca',\n            BLUEMAIL: 'BlueMail',\n            CANARY: 'Canary',\n            CLAWS_MAIL: 'Claws Mail',\n            DAUM_MAIL: 'DaumMail',\n            EM_CLIENT: 'eM Client',\n            EUDORA: 'Eudora',\n            EVOLUTION: 'Evolution',\n            FAIR_EMAIL: 'FairEmail',\n            FOXMAIL: 'Foxmail',\n            GEARY: 'Geary',\n            GNUS: 'Gnus',\n            HORDE_IMP: 'Horde::IMP',\n            IBM_NOTES: 'Lotus-Notes',\n            INCREDIMAIL: 'IncrediMail',\n            K9_MAIL: 'K-9 Mail',\n            KMAIL: 'KMail',\n            KMAIL2: 'kmail2',\n            KONTACT: 'Kontact',\n            MAILBIRD: 'Mailbird',\n            MAILMATE: 'MailMate',\n            MAILSPRING: 'Mailspring',\n            MICROSOFT_OUTLOOK: 'Microsoft Outlook',\n            MICROSOFT_OUTLOOK_MAC: 'MacOutlook',\n            MUTT: 'Mutt',\n            NAVER_MAILAPP: 'NaverMailApp',\n            NEWTON: 'Newton',\n            NINE: 'Nine',\n            NYLAS_MAIL: 'NylasMail',\n            OUTLOOK_EXPRESS: 'Outlook-Express',\n            PEGASUS_MAIL: 'Pegasus Mail',\n            POCOMAIL: 'PocoMail',\n            POLYMAIL: 'Polymail',\n            POSTBOX: 'Postbox',\n            PROTON_MAIL: 'ProtonMail',\n            PROTON_MAIL_BRIDGE: 'ProtonMail Bridge',\n            QUALA_MAIL: 'Quala',\n            R2MAIL2: 'R2Mail2',\n            RAINLOOP: 'RainLoop',\n            ROUNDCUBE: 'Roundcube Webmail',\n            SAMSUNG_EMAIL: 'SamsungEmail',\n            SPARK_MAIL: 'SparkDesktop',\n            SPARROW: 'Sparrow',\n            SPICEBIRD: 'Spicebird',\n            SQUIRRELMAIL: 'SquirrelMail',\n            SYLPHEED: 'Sylpheed',\n            THE_BAT: 'The Bat!',\n            THUNDERBIRD: 'Thunderbird',\n            TROJITA: 'Trojita',\n            TURNPIKE: 'Turnpike',\n            TUTANOTA: 'tutanota-desktop',\n            WANDERLUST: 'Wanderlust',\n            WINDOWS_LIVE_MAIL: 'Windows-Live-Mail',\n            YAHOO_MAIL: 'Yahoo Mail',\n            YAHOO_MAIL_IOS: 'Yahoo Mail',\n            ZIMBRA: 'Zimbra',\n            ZOHO_MAIL: 'ZohoMail-Desktop'\n        },\n        Fetcher: {\n            AHREFS_SITEAUDIT: 'AhrefsSiteAudit',\n            AMAZON_NOVA_ACT: 'NovaAct',\n            ANTHROPIC_CLAUDE_USER: 'Claude-User',\n            ASANA: 'Asana',\n            BETTER_UPTIME_BOT: 'Better Uptime Bot',\n            BITLY_BOT: 'bitlybot',\n            BLUESKY: 'Bluesky',\n            BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',\n            COHERE_AI: 'Cohere-AI',\n            DISCORD_BOT: 'Discordbot',\n            DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',\n            FEEDLY: 'Feedly',\n            FLIPBOARD_PROXY: 'FlipboardProxy',\n            GOOGLE_CHROME_LIGHTHOUSE: 'Lighthouse',\n            GOOGLE_DOCS: 'GoogleDocs',\n            GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',\n            GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research',\n            GOOGLE_IMAGEPROXY: 'GoogleImageProxy',\n            GOOGLE_PAGERENDERER: 'Google-PageRenderer',\n            GOOGLE_READ_ALOUD: 'Google-Read-Aloud',\n            GOOGLE_PRODUCER: 'GoogleProducer',\n            GOOGLE_SITE_VERIFICATION: 'Google-Site-Verification',\n            HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',\n            IFRAMELY: 'Iframely',\n            KAKAOTALK_SCRAP: 'kakaotalk-scrap',\n            KEYBASE_BOT: 'KeybaseBot',\n            META_EXTERNALFETCHER: 'meta-externalfetcher',\n            META_WHATSAPP: 'WhatsApp',\n            MICROSOFT_BINGPREVIEW: 'BingPreview',\n            MICROSOFT_PREVIEW: 'MicrosoftPreview',\n            MISTRALAI_USER: 'MistralAI-User',\n            NAVER_BLUENO: 'Blueno',\n            ONCRAWL_ROGERBOT: 'rogerbot',\n            OPENAI_CHATGPT_USER: 'ChatGPT-User',\n            PERPLEXITY_USER: 'Perplexity-User',\n            PINTEREST_BOT: 'Pinterestbot',\n            SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',\n            SLACK_BOT: 'Slackbot',\n            SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',\n            SLACK_IMGPROXY: 'Slack-ImgProxy',\n            SNAP_URL_PREVIEW: 'Snap URL Preview',\n            SKYPE_URIPREVIEW: 'SkypeUriPreview',\n            TELEGRAM_BOT: 'TelegramBot',\n            UPTIMEROBOT: 'UptimeRobot',\n            UPTIMEBOT: 'UptimeBot',\n            VERCEL_FAVICON_BOT: 'vercel-favicon-bot',\n            VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',\n            VERCEL_BOT: 'Vercelbot',\n            VERCEL_FLAGS: 'vercelflags',\n            VERCEL_TRACING: 'verceltracing',\n            VIRUSTOTAL: 'virustotal',\n            X_TWITTERBOT: 'Twitterbot',\n            YANDEX_CALENDAR: 'YandexCalendar',\n            YANDEX_DIRECT: 'YandexDirect',\n            YANDEX_DIRECTDYN: 'YandexDirectDyn',\n            YANDEX_DIRECTFETCHER: 'YaDirectFetcher',\n            YANDEX_FORDOMAIN: 'YandexForDomain',\n            YANDEX_PAGECHECKER: 'YandexPagechecker',\n            YANDEX_SEARCHSHOP: 'YandexSearchShop',\n            YANDEX_SITELINKS: 'YandexSitelinks',\n            YANDEX_USERPROXY: 'YandexUserproxy',\n            ZOOMINFO_BOT: 'Zoombot'\n        },\n        InApp: {\n            DISCORD: 'Discord',\n            EVERNOTE: 'Evernote',\n            FIGMA: 'Figma',\n            FLIPBOARD: 'Flipboard',\n            MATTERMOST: 'Mattermost',\n            TEAMS: 'Teams',\n            NOTION: 'Notion',\n            POSTMAN: 'Postman',\n            RAMBOX: 'Rambox',\n            ROCKETCHAT: 'Rocket.Chat',\n            SLACK: 'Slack',\n            TIKTOK_LITE: 'TikTok Lite',\n            VSCODE: 'VS Code',\n            YAHOO_JAPAN: 'Yahoo! Japan'\n        },\n        Library: {\n            ADOBE_AIR: 'AdobeAIR',\n            AIOHTTP: 'aiohttp',\n            APACHE_HTTPCLIENT: 'Apache-HttpClient',\n            AXIOS: 'axios',\n            BUN: 'Bun',\n            DART: 'Dart',\n            DENO: 'Deno',\n            GO_HTTP_CLIENT: 'go-http-client',\n            GOT: 'got',\n            GUZZLEHTTP: 'GuzzleHttp',\n            HACKNEY: 'hackney',\n            HTTP_RB: 'http.rb',\n            JAVA: 'Java',\n            JAVA_HTTPCLIENT: 'Java-http-client',\n            JETTY: 'Jetty',\n            JSDOM: 'jsdom',\n            LIBWWW_PERL: 'libwww-perl',\n            LUA_RESTY_HTTP: 'lua-resty-http',\n            NEEDLE: 'Needle',\n            NUTCH: 'Nutch',\n            NODE_FETCH: 'node-fetch',\n            NODE_JS: 'Node.js',\n            NODE_SUPERAGENT: 'node-superagent',\n            OKHTTP: 'OkHttp',\n            OCAML_COHTTP: 'ocaml-cohttp',\n            PHP_CRAWL: 'phpcrawl',\n            PHP_SOAP: 'PHP-SOAP',\n            POSTMAN_RUNTIME: 'PostmanRuntime',\n            PYTHON_HTTPX: 'python-httpx',\n            PYTHON_URLLIB: 'python-urllib',\n            PYTHON_URLLIB3: 'python-urllib3',\n            PYTHON_REQUESTS: 'python-requests',\n            REST_CLIENT: 'rest-client',\n            SCRAPY: 'Scrapy',\n            UNDICI: 'undici'\n        }\n    },\n    DeviceVendor: {\n        Vehicle: {\n            BMW: 'BMW',\n            BYD: 'BYD',\n            JEEP: 'Jeep',\n            RIVIAN: 'Rivian',\n            TESLA: 'Tesla',\n            VOLVO: 'Volvo'\n        }\n    }\n});\n\nmodule.exports = { \n    Browser,// deprecated\n    CPU,    // deprecated\n    Device, // deprecated\n    Vendor, // deprecated\n    Engine, // deprecated\n    OS,     // deprecated\n    BrowserName,\n    BrowserType, \n    CPUArch,\n    DeviceType, \n    DeviceVendor,\n    EngineName,\n    OSName,\n    Extension\n};"
  },
  {
    "path": "src/enums/ua-parser-enums.mjs",
    "content": "// Generated ESM version of ua-parser-js/enums\n// DO NOT EDIT THIS FILE!\n// Source: /src/enums/ua-parser-enums.js\n\n///////////////////////////////////////////////\n/*  Enums for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst BrowserName = Object.freeze({\n    '115': '115',\n    '2345': '2345',\n    '360': '360',\n    ALIPAY: 'Alipay',\n    ALOHA: 'Aloha',\n    AMAYA: 'Amaya',\n    ANDROID: 'Android Browser',\n    ARORA: 'Arora',\n    ATLAS: 'Atlas',\n    AVANT: 'Avant',\n    AVAST: 'Avast Secure Browser',\n    AVG: 'AVG Secure Browser',\n    AVIRA: 'Avira Secure Browser',\n    BAIDU: 'Baidu Browser',\n    BASILISK: 'Basilisk',\n    BING: 'Bing',\n    BLAZER: 'Blazer',\n    BOLT: 'Bolt',\n    BOWSER: 'Bowser',\n    BRAVE: 'Brave',\n    CAMINO: 'Camino',\n    CHIMERA: 'Chimera',\n    CHROME: 'Chrome',\n    CHROME_HEADLESS: 'Chrome Headless',\n    CHROME_MOBILE: 'Mobile Chrome',\n    CHROME_WEBVIEW: 'Chrome WebView',\n    CHROMIUM: 'Chromium',\n    COBALT: 'Cobalt',\n    COC_COC: 'Coc Coc',\n    CONKEROR: 'Conkeror',\n    DAUM: 'Daum',\n    DILLO: 'Dillo',\n    DOLPHIN: 'Dolphin',\n    DOOBLE: 'Dooble',\n    DORIS: 'Doris',\n    DRAGON: 'Dragon',\n    DUCKDUCKGO: 'DuckDuckGo',\n    ECOSIA: 'Ecosia',\n    EDGE: 'Edge',\n    EDGE_WEBVIEW: 'Edge WebView',\n    EDGE_WEBVIEW2: 'Edge WebView2',\n    EPIPHANY: 'Epiphany',\n    FACEBOOK: 'Facebook',\n    FALKON: 'Falkon',\n    FIREBIRD: 'Firebird',\n    FIREFOX: 'Firefox',\n    FIREFOX_FOCUS: 'Firefox Focus',\n    FIREFOX_MOBILE: 'Mobile Firefox',\n    FIREFOX_REALITY: 'Firefox Reality',\n    FENNEC: 'Fennec',\n    FLOCK: 'Flock',\n    FLOW: 'Flow',\n    GO: 'GoBrowser',\n    GOOGLE_SEARCH: 'GSA',\n    HELIO: 'Helio',\n    HEYTAP: 'HeyTap',\n    HIBROWSER: 'HiBrowser',\n    HONOR: 'Honor',\n    HUAWEI: 'Huawei Browser',\n    ICAB: 'iCab',\n    ICE: 'ICE Browser',\n    ICEAPE: 'IceApe',\n    ICECAT: 'IceCat',\n    ICEDRAGON: 'IceDragon',\n    ICEWEASEL: 'IceWeasel',\n    IE: 'IE',\n    INSTAGRAM: 'Instagram',\n    IRIDIUM: 'Iridium',\n    IRON: 'Iron',\n    JASMINE: 'Jasmine',\n    KONQUEROR: 'Konqueror',\n    KAKAO: 'KakaoTalk',\n    KHTML: 'KHTML',\n    K_MELEON: 'K-Meleon',\n    KLAR: 'Klar',\n    KLARNA: 'Klarna',\n    KINDLE: 'Kindle',\n    LENOVO: 'Smart Lenovo Browser',\n    LADYBIRD: 'Ladybird',\n    LG: 'LG Browser',\n    LIBREWOLF: 'LibreWolf',\n    LIEBAO: 'LBBROWSER',\n    LIGHTHOUSE: 'Lighthouse',\n    LINE: 'Line',\n    LINKEDIN: 'LinkedIn',\n    LINKS: 'Links',\n    LUAKIT: 'Luakit',\n    LUNASCAPE: 'Lunascape',\n    LYNX: 'Lynx',\n    MAEMO: 'Maemo Browser',\n    MAXTHON: 'Maxthon',\n    MIDORI: 'Midori',\n    MINIMO: 'Minimo',\n    MIUI: 'MIUI Browser',\n    MOZILLA: 'Mozilla',\n    MOSAIC: 'Mosaic',\n    NAVER: 'Naver',\n    NETFRONT: 'NetFront',\n    NETSCAPE: 'Netscape',\n    NETSURF: 'Netsurf',\n    NOKIA: 'Nokia Browser',\n    NORTON: 'Norton Private Browser',\n    OBIGO: 'Obigo',\n    OCULUS: 'Oculus Browser',\n    OMNIWEB: 'OmniWeb',\n    OPERA: 'Opera',\n    OPERA_COAST: 'Opera Coast',\n    OPERA_GX: 'Opera GX',\n    OPERA_MINI: 'Opera Mini',\n    OPERA_MOBI: 'Opera Mobi',\n    OPERA_NEON: 'Opera Neon',\n    OPERA_TABLET: 'Opera Tablet',\n    OPERA_TOUCH: 'Opera Touch',\n    OTTER: 'Otter',\n    OVI: 'OviBrowser',\n    PALEMOON: 'PaleMoon',\n    PHANTOMJS: 'PhantomJS',\n    PHOENIX: 'Phoenix',\n    PICOBROWSER: 'Pico Browser',\n    POLARIS: 'Polaris',\n    PUFFIN: 'Puffin',\n    QQ: 'QQBrowser',\n    QQ_LITE: 'QQBrowserLite',\n    QUARK: 'Quark',\n    QUPZILLA: 'QupZilla',\n    QUTEBROWSER: 'qutebrowser',\n    QWANT: 'Qwant',\n    REKONQ: 'rekonq',\n    ROCKMELT: 'Rockmelt',\n    SAFARI: 'Safari',\n    SAFARI_MOBILE: 'Mobile Safari',\n    SAILFISH: 'Sailfish Browser',\n    SAMSUNG: 'Samsung Internet',\n    SEAMONKEY: 'SeaMonkey',\n    SILK: 'Silk',\n    SKYFIRE: 'Skyfire',\n    SLEIPNIR: 'Sleipnir',\n    SLIMBOAT: 'SlimBoat',\n    SLIMBROWSER: 'SlimBrowser',\n    SLIMJET: 'Slimjet',\n    SNAPCHAT: 'Snapchat',\n    SOGOU_EXPLORER: 'Sogou Explorer',\n    SOGOU_MOBILE: 'Sogou Mobile',\n    STEAM: 'Steam',\n    SURF: 'Surf',\n    SWIFTFOX: 'Swiftfox',\n    TESLA: 'Tesla',\n    TIKTOK: 'TikTok',\n    TIZEN: 'Tizen Browser',\n    TWITTER: 'Twitter',\n    UC: 'UCBrowser',\n    UP: 'UP.Browser',\n    VIVALDI: 'Vivaldi',\n    VIVO: 'Vivo Browser',\n    W3M: 'w3m',\n    WATERFOX: 'Waterfox',\n    WEBKIT: 'WebKit',\n    WECHAT: 'WeChat',\n    WEIBO: 'Weibo',\n    WHALE: 'Whale',\n    WOLVIC: 'Wolvic',\n    YANDEX: 'Yandex',\n    ZALO: 'Zalo'\n\n    // TODO : test!\n});\n/**\n * @deprecated Use `BrowserName` instead\n */\nconst Browser = BrowserName;\n\nconst BrowserType = Object.freeze({\n    CRAWLER: 'crawler',\n    CLI: 'cli',\n    EMAIL: 'email',\n    FETCHER: 'fetcher',\n    INAPP: 'inapp',\n    MEDIAPLAYER: 'mediaplayer',\n    LIBRARY: 'library'\n});\n\nconst CPUArch = Object.freeze({\n    '68K': '68k',\n    ALPHA: 'alpha',\n    ARM : 'arm',\n    ARM_64: 'arm64',\n    ARM_HF: 'armhf',\n    AVR: 'avr',\n    AVR_32: 'avr32',\n    IA64: 'ia64',\n    IRIX: 'irix',\n    IRIX_64: 'irix64',\n    MIPS: 'mips',\n    MIPS_64: 'mips64',\n    PA_RISC: 'pa-risc',\n    PPC: 'ppc',\n    SPARC: 'sparc',\n    SPARC_64: 'sparc64',\n    X86: 'ia32',\n    X86_64: 'amd64'\n});\n/**\n * @deprecated Use `CPUArch` instead\n */\nconst CPU = CPUArch;\n\nconst DeviceType = Object.freeze({\n    CONSOLE: 'console',\n    EMBEDDED: 'embedded',\n    MOBILE: 'mobile',\n    SMARTTV: 'smarttv',\n    TABLET: 'tablet',\n    WEARABLE: 'wearable',\n    XR: 'xr'\n});\n/**\n * @deprecated Use `DeviceType` instead\n */\nconst Device = DeviceType;\n\nconst DeviceVendor = Object.freeze({\n    ACER: 'Acer',\n    ADVAN: 'Advan',\n    ALCATEL: 'Alcatel',\n    AMAZON: 'Amazon',\n    ANBERNIC: 'Anbernic',\n    APPLE: 'Apple',\n    ARCHOS: 'Archos',\n    ASUS: 'ASUS',\n    ATT: 'AT&T',\n    BENQ: 'BenQ',\n    BLACKBERRY: 'BlackBerry',\n    BLU: 'BLU',\n    CAT: 'Cat',\n    DELL: 'Dell',\n    ENERGIZER: 'Energizer',\n    ESSENTIAL: 'Essential',\n    FACEBOOK: 'Facebook',\n    FAIRPHONE: 'Fairphone',\n    GEEKSPHONE: 'GeeksPhone',\n    GENERIC: 'Generic',\n    GOOGLE: 'Google',\n    HISENSE: 'Hisense',\n    HMD: 'HMD',\n    HP: 'HP',\n    HTC: 'HTC',\n    HUAWEI: 'Huawei',\n    IMO: 'IMO',\n    INFINIX: 'Infinix',\n    ITEL: 'itel',\n    JOLLA: 'Jolla',\n    KOBO: 'Kobo',\n    LAVA: 'Lava',\n    LENOVO: 'Lenovo',\n    LG: 'LG',\n    LOGITECH: 'Logitech',\n    MEIZU: 'Meizu',\n    MICROMAX: 'Micromax',\n    MICROSOFT: 'Microsoft',\n    MOTOROLA: 'Motorola',\n    NEXIAN: 'Nexian',\n    NINTENDO: 'Nintendo',\n    NOKIA: 'Nokia',\n    NOTHING: 'Nothing',\n    NVIDIA: 'Nvidia',\n    ONEPLUS: 'OnePlus',\n    OPPO: 'OPPO',\n    OUYA: 'Ouya',\n    PALM: 'Palm',\n    PANASONIC: 'Panasonic',\n    PEBBLE: 'Pebble',\n    PHILIPS: 'Philips',\n    PICO: 'Pico',\n    POLYTRON: 'Polytron',\n    REALME: 'Realme',\n    RETROID: 'Retroid',\n    RIM: 'RIM',\n    ROKU: 'Roku',\n    SAMSUNG: 'Samsung',\n    SHARP: 'Sharp',\n    SIEMENS: 'Siemens',\n    SMARTFREN: 'Smartfren',\n    SONY: 'Sony',\n    SPRINT: 'Sprint',\n    TCL: 'TCL',\n    TECHNISAT: 'TechniSAT',\n    TECNO: 'TECNO',\n    TESLA: 'Tesla',\n    ULEFONE: 'Ulefone',\n    VALVE: 'Valve',\n    VIVO: 'Vivo',\n    VIZIO: 'Vizio',\n    VODAFONE: 'Vodafone',\n    WIKO: 'Wiko',\n    XBOX: 'Xbox',\n    XIAOMI: 'Xiaomi',\n    ZEBRA: 'Zebra',\n    ZTE: 'ZTE',\n\n    // TODO : test!\n});\n/**\n * @deprecated Use `DeviceVendor` instead\n */\nconst Vendor = DeviceVendor;\n\nconst EngineName = Object.freeze({\n    AMAYA: 'Amaya',\n    ARKWEB: 'ArkWeb',\n    BLINK: 'Blink',\n    DILLO: 'Dillo',\n    EDGEHTML: 'EdgeHTML',\n    FLOW: 'Flow',\n    GECKO: 'Gecko',\n    GOANNA: 'Goanna',\n    ICAB: 'iCab',\n    KHTML: 'KHTML',\n    LIBWEB: 'LibWeb',\n    LINKS: 'Links',\n    LYNX: 'Lynx',\n    NETFRONT: 'NetFront',\n    NETSURF: 'NetSurf',\n    PRESTO: 'Presto',\n    SERVO: 'Servo',\n    TASMAN: 'Tasman',\n    TRIDENT: 'Trident',\n    W3M: 'w3m',\n    WEBKIT: 'WebKit'\n});\n/**\n * @deprecated Use `EngineName` instead\n */\nconst Engine = EngineName;\n\nconst OSName = Object.freeze({\n    AIX: 'AIX',\n    AMIGA_OS: 'Amiga OS',\n    ANDROID: 'Android',\n    ANDROID_X86: 'Android-x86',\n    ARCAOS: 'ArcaOS',\n    ARCH: 'Arch',\n    BADA: 'Bada',\n    BEOS: 'BeOS',\n    BLACKBERRY: 'BlackBerry',\n    CENTOS: 'CentOS',\n    CHROME_OS: 'Chrome OS',\n    CHROMECAST: 'Chromecast',\n    CHROMECAST_ANDROID: 'Chromecast Android',\n    CHROMECAST_FUCHSIA: 'Chromecast Fuchsia',\n    CHROMECAST_LINUX: 'Chromecast Linux',\n    CHROMECAST_SMARTSPEAKER: 'Chromecast SmartSpeaker',\n    CONTIKI: 'Contiki',\n    DEBIAN: 'Debian',\n    DEEPIN: 'Deepin',\n    DRAGONFLY: 'DragonFly',\n    ELEMENTARY_OS: 'elementary OS',\n    FEDORA: 'Fedora',\n    FIREFOX_OS: 'Firefox OS',\n    FREEBSD: 'FreeBSD',\n    FUCHSIA: 'Fuchsia',\n    GENTOO: 'Gentoo',\n    GHOSTBSD: 'GhostBSD',\n    GNU: 'GNU',\n    HAIKU: 'Haiku',\n    HARMONYOS: 'HarmonyOS',\n    HP_UX: 'HP-UX',\n    HURD: 'Hurd',\n    IOS: 'iOS',\n    JOLI: 'Joli',\n    KAIOS: 'KaiOS',\n    KNOPPIX: 'Knoppix',\n    KUBUNTU: 'Kubuntu',\n    LINPUS: 'Linpus',\n    LINSPIRE: 'Linspire',\n    LINUX: 'Linux',\n    MACOS: 'macOS',\n    MAEMO: 'Maemo',\n    MAGEIA: 'Mageia',\n    MANDRIVA: 'Mandriva',\n    MANJARO: 'Manjaro',\n    MEEGO: 'MeeGo',\n    MINIX: 'Minix',\n    MINT: 'Mint',\n    MORPH_OS: 'Morph OS',\n    NETBSD: 'NetBSD',\n    NETRANGE: 'NetRange',\n    NETTV: 'NetTV',\n    NINTENDO: 'Nintendo',\n    OPENHARMONY: 'OpenHarmony',\n    OPENBSD: 'OpenBSD',\n    OPENVMS: 'OpenVMS',\n    OS2: 'OS/2',\n    PALM: 'Palm',\n    PC_BSD: 'PC-BSD',\n    PCLINUXOS: 'PCLinuxOS',\n    PICO: 'Pico',\n    PLAN9: 'Plan9',\n    PLAYSTATION: 'PlayStation',\n    QNX: 'QNX',\n    RASPBIAN: 'Raspbian',\n    REDHAT: 'RedHat',\n    RIM_TABLET_OS: 'RIM Tablet OS',\n    RISC_OS: 'RISC OS',\n    SABAYON: 'Sabayon',\n    SAILFISH: 'Sailfish',\n    SERENITYOS: 'SerenityOS',\n    SERIES40: 'Series40',\n    SLACKWARE: 'Slackware',\n    SOLARIS: 'Solaris',\n    SUSE: 'SUSE',\n    SYMBIAN: 'Symbian',\n    TIZEN: 'Tizen',\n    UBUNTU: 'Ubuntu',\n    UBUNTU_TOUCH: 'Ubuntu Touch',\n    UNIX: 'Unix',\n    VECTORLINUX: 'VectorLinux',\n    VEGA_OS: 'Vega OS',\n    WATCHOS: 'watchOS',\n    WEBOS: 'WebOS',\n    WINDOWS: 'Windows',\n    WINDOWS_CE: 'Windows CE',\n    WINDOWS_IOT: 'Windows IoT',\n    WINDOWS_MOBILE: 'Windows Mobile',\n    WINDOWS_PHONE: 'Windows Phone',\n    WINDOWS_RT: 'Windows RT',\n    XBOX: 'Xbox',\n    XUBUNTU: 'Xubuntu',\n    ZENWALK: 'Zenwalk'\n\n    // TODO : test!\n});\n/**\n * @deprecated Use `OSName` instead\n */\nconst OS = OSName;\n\n/*////////////////////////////////\n * Enums for Extensions submodule\n *///////////////////////////////\n\nconst Extension = Object.freeze({\n    BrowserName: {\n        CLI: {\n            CURL: 'curl',\n            ELINKS: 'ELinks',\n            HTTPIE: 'HTTPie',\n            LYNX: 'Lynx',\n            POWERSHELL: 'PowerShell',\n            WGET: 'Wget'\n        },\n        Crawler: {\n            AHREFS_BOT: 'AhrefsBot',\n            AI2_BOT: 'AI2Bot',\n            AIHIT_BOT: 'aiHitBot',\n            ALGOLIA_CRAWLER: 'Algolia Crawler',\n            APPLE_BOT: 'Applebot',\n            APPLE_BOT_EXTENDED: 'Applebot-Extended',\n            ASK_TEOMA: 'Teoma',\n            AMAZON_BOT: 'Amazonbot',\n            AMAZON_CONTXBOT: 'contxbot',\n            ANTHROPIC_AI: 'anthropic-ai',\n            ANTHROPIC_CLAUDE_BOT: 'ClaudeBot',\n            ANTHROPIC_CLAUDE_SEARCHBOT: 'Claude-SearchBot',\n            ANTHROPIC_CLAUDE_WEB: 'Claude-Web',\n            ATLASSIAN_BOT: 'atlassian-bot',\n            ARCHIVEORG_BOT: 'archive.org_bot',\n            BAIDU_ADS: 'Baidu-ADS',\n            BAIDU_SPIDER: 'Baiduspider',\n            BAIDU_SPIDER_ADS: 'Baiduspider-ads',\n            BAIDU_SPIDER_CPRO: 'Baiduspider-cpro',\n            BAIDU_SPIDER_FAVO: 'Baiduspider-favo',\n            BAIDU_SPIDER_IMAGE: 'Baiduspider-image',\n            BAIDU_SPIDER_NEWS: 'Baiduspider-news',\n            BAIDU_SPIDER_RENDER: 'Baiduspider-render',\n            BAIDU_SPIDER_VIDEO: 'Baiduspider-video',\n            BLEX_BOT: 'BLEXBot',\n            BOTIFY: 'botify',\n            BRAVE_BOT: 'Bravebot',\n            BYTEDANCE_BYTESPIDER: 'Bytespider',\n            BYTEDANCE_TIKTOKSPIDER: 'TikTokSpider',\n            CLOUDFLARE_AUTORAG: 'Cloudflare-AutoRAG',\n            COMMON_CRAWL_CCBOT: 'CCBot',\n            COCCOC_BOT_WEB: 'coccocbot-web',\n            COCCOC_BOT_IMAGE: 'coccocbot-image',\n            COHERE_TRAINING_DATA_CRAWLER: 'cohere-training-data-crawler',\n            COTOYOGI: 'Cotoyogi',\n            COVEO_BOT: 'Coveobot',\n            CRITEO_BOT: 'CriteoBot',\n            DATAFORSEO_BOT: 'DataForSeoBot',\n            DAUM: 'Daum',\n            DAUM_DAUMOA: 'Daumoa',\n            DAUM_DAUMOA_IMAGE: 'Daumoa-image',\n            DEEPSEEK_BOT: 'DeepSeekBot',\n            DIFFBOT: 'Diffbot',\n            DUCKDUCKGO_BOT: 'DuckDuckBot',\n            DUCKDUCKGO_FAVICONS_BOT: 'DuckDuckGo-Favicons-Bot',\n            ELASTIC: 'Elastic',\n            ELASTIC_SWIFTYPE_BOT: 'Swiftbot',\n            EXALEAD_EXABOT: 'Exabot',\n            FIRECRAWL_AGENT: 'FirecrawlAgent',\n            FREESPOKE: 'Freespoke',\n            GOOGLE_ADSBOT: 'AdsBot-Google',\n            GOOGLE_ADSBOT_MOBILE: 'Adsbot-Google-Mobile',\n            GOOGLE_ADSENSE: 'AdSense',\n            GOOGLE_APIS: 'APIs-Google',\n            GOOGLE_BOT: 'Googlebot',\n            GOOGLE_BOT_IMAGE: 'Googlebot-Image',\n            GOOGLE_BOT_NEWS: 'Googlebot-News',\n            GOOGLE_BOT_VIDEO: 'Googlebot-Video',\n            GOOGLE_CLOUDVERTEXBOT: 'Google-CloudVertexBot',\n            GOOGLE_EXTENDED: 'Google-Extended',\n            GOOGLE_INSPECTIONTOOL: 'Google-InspectionTool',\n            GOOGLE_NOTEBOOKLM: 'Google-NotebookLM',\n            GOOGLE_OTHER: 'GoogleOther',\n            GOOGLE_OTHER_IMAGE: 'GoogleOther-Image',\n            GOOGLE_OTHER_VIDEO: 'GoogleOther-Video',\n            GOOGLE_SAFETY: 'Google-Safety',\n            GOOGLE_STOREBOT: 'Storebot-Google',\n            HIVE_IMAGESIFTBOT: 'ImagesiftBot',\n            HUAWEI_PANGUBOT: 'PanguBot',\n            HUAWEI_PETALBOT: 'PetalBot',\n            HUGGINGFACE_BOT: 'HuggingFace-Bot',\n            HUNTER_VELENPUBLICWEBCRAWLER: 'VelenPublicWebCrawler',\n            IA_ARCHIVER: 'ia_archiver',\n            IASK_BOT: 'iAskBot',\n            KAGI_BOT: 'Kagibot',\n            KANGAROO_BOT: 'Kangaroo Bot',\n            LINE_SPIDER: 'Linespider',\n            LINKEDIN_BOT: 'LinkedInBot',\n            MAGPIE_CRAWLER: 'magpie-crawler',\n            MARGINALIA: 'marginalia',\n            META_EXTERNALAGENT: 'meta-externalagent',\n            META_FACEBOOKBOT: 'FacebookBot',\n            META_FACEBOOKCATALOG: 'facebookcatalog',\n            META_FACEBOOKEXTERNALHIT: 'facebookexternalhit',\n            MAJESTIC_MJ12BOT: 'MJ12bot',\n            MICROSOFT_BINGBOT: 'Bingbot',\n            MICROSOFT_MSNBOT: 'msnbot',\n            MICROSOFT_ADIDXBOT: 'adidxbot',\n            MOJEEK_BOT: 'MojeekBot',\n            MOZ_DOTBOT: 'DotBot',\n            ONCRAWL: 'OnCrawl',\n            ONESPOT_SCRAPERBOT: 'Onespot-ScraperBot',\n            OPENAI_GPTBOT: 'GPTBot',\n            OPENAI_SEARCH_BOT: 'OAI-SearchBot',\n            PERPLEXITY_BOT: 'PerplexityBot',\n            QIHOO_360_SPIDER: '360Spider',\n            QWANT_BOT: 'Qwantbot',\n            QWANT_BOT_NEWS: 'Qwantbot-news',\n            REPLICATE_BOT: 'Replicate-Bot',\n            RUNPOD_BOT: 'RunPod-Bot',\n            SB_INTUITIONS_BOT: 'SBIntuitionsBot',\n            SEEKPORT_BOT: 'SeekportBot',\n            SEMRUSH_BOT: 'SemrushBot',\n            SEMRUSH_BOT_BACKLINK: 'SemrushBot-BA',\n            SEMRUSH_BOT_CONTENTSHAKE: 'SemrushBot-OCOB',\n            SEMRUSH_BOT_SEO_CHECKER: 'SemrushBot-SI',\n            SEMRUSH_BOT_SWA: 'SemrushBot-SWA',\n            SEZNAM_BOT: 'SeznamBot',\n            SITEIMPROVE: 'Siteimprove',\n            SOGOU_PIC_SPIDER: 'Sogou Pic Spider',\n            SOGOU_WEB_SPIDER: 'Sogou web spider',\n            STARTPAGE: 'Startpage',\n            SURLY_BOT: 'SurdotlyBot',\n            TIMPI_BOT: 'Timpibot',\n            TOGETHER_BOT: 'Together-Bot',\n            TURNITIN_BOT: 'TurnitinBot',\n            TWIN_AGENT: 'TwinAgent',\n            VERCEL_V0BOT: 'v0bot',\n            WEBZIO: 'webzio',\n            WEBZIO_EXTENDED: 'Webzio-Extended',\n            WEBZIO_OMGILI: 'omgili',\n            WEBZIO_OMGILI_BOT: 'omgilibot',\n            XAI_BOT: 'xAI-Bot',\n            YAHOO_JAPAN: 'Y!J-BRW',\n            YAHOO_SLURP: 'Yahoo! Slurp',\n            YANDEX_ACCESSIBILITY_BOT: 'YandexAccessibilityBot',\n            YANDEX_ADDITIONAL_BOT: 'YandexAdditionalBot',\n            YANDEX_ADNET: 'YandexAdNet',\n            YANDEX_BLOGS: 'YandexBlogs',\n            YANDEX_BOT: 'YandexBot',\n            YANDEX_BOT_MIRRORDETECTOR: 'YandexBot MirrorDetector',\n            YANDEX_COMBOT: 'YandexComBot',\n            YANDEX_FAVICONS: 'YandexFavicons',\n            YANDEX_IMAGE_RESIZER: 'YandexImageResizer',\n            YANDEX_IMAGES: 'YandexImages',\n            YANDEX_MARKET: 'YandexMarket',\n            YANDEX_MEDIA: 'YandexMedia',\n            YANDEX_METRIKA: 'YandexMetrika',\n            YANDEX_MOBILE_BOT: 'YandexMobileBot',\n            YANDEX_MOBILE_SCREENSHOT_BOT: 'YandexMobileScreenShotBot',\n            YANDEX_NEWS: 'YandexNews',\n            YANDEX_ONTODB: 'YandexOntoDB',\n            YANDEX_ONTODB_API: 'YandexOntoDBAPI',\n            YANDEX_PARTNER: 'YandexPartner',\n            YANDEX_RCA: 'YandexRCA',\n            YANDEX_RENDERRESOURCES_BOT: 'YandexRenderResourcesBot',\n            YANDEX_SCREENSHOT_BOT: 'YandexScreenshotBot',\n            YANDEX_SPRAV_BOT: 'YandexSpravBot',\n            YANDEX_TRACKER: 'YandexTracker',\n            YANDEX_VERTICALS: 'YandexVerticals',\n            YANDEX_VERTIS: 'YandexVertis',\n            YANDEX_VIDEO: 'YandexVideo',\n            YANDEX_VIDEO_PARSER: 'YandexVideoParser',\n            YANDEX_WEBMASTER: 'YandexWebmaster',\n            YEP_BOT: 'YepBot',\n            YETI: 'Yeti',\n            YISOU_SPIDER: 'YisouSpider',\n            YOU_BOT: 'YouBot',\n            ZHIPU_CHATGLM_SPIDER: 'ChatGLM-Spider',\n            ZUM_BOT: 'ZumBot'\n        },\n        Email: {\n            AIRMAIL: 'Airmail',\n            ALPINE: 'Alpine',\n            ANDROID_MAIL: 'Android',\n            APPLE_MAIL: 'Mail',\n            AQUA_MAIL: 'AquaMail',\n            BALSA: 'Balsa',\n            BARCA: 'Barca',\n            BLUEMAIL: 'BlueMail',\n            CANARY: 'Canary',\n            CLAWS_MAIL: 'Claws Mail',\n            DAUM_MAIL: 'DaumMail',\n            EM_CLIENT: 'eM Client',\n            EUDORA: 'Eudora',\n            EVOLUTION: 'Evolution',\n            FAIR_EMAIL: 'FairEmail',\n            FOXMAIL: 'Foxmail',\n            GEARY: 'Geary',\n            GNUS: 'Gnus',\n            HORDE_IMP: 'Horde::IMP',\n            IBM_NOTES: 'Lotus-Notes',\n            INCREDIMAIL: 'IncrediMail',\n            K9_MAIL: 'K-9 Mail',\n            KMAIL: 'KMail',\n            KMAIL2: 'kmail2',\n            KONTACT: 'Kontact',\n            MAILBIRD: 'Mailbird',\n            MAILMATE: 'MailMate',\n            MAILSPRING: 'Mailspring',\n            MICROSOFT_OUTLOOK: 'Microsoft Outlook',\n            MICROSOFT_OUTLOOK_MAC: 'MacOutlook',\n            MUTT: 'Mutt',\n            NAVER_MAILAPP: 'NaverMailApp',\n            NEWTON: 'Newton',\n            NINE: 'Nine',\n            NYLAS_MAIL: 'NylasMail',\n            OUTLOOK_EXPRESS: 'Outlook-Express',\n            PEGASUS_MAIL: 'Pegasus Mail',\n            POCOMAIL: 'PocoMail',\n            POLYMAIL: 'Polymail',\n            POSTBOX: 'Postbox',\n            PROTON_MAIL: 'ProtonMail',\n            PROTON_MAIL_BRIDGE: 'ProtonMail Bridge',\n            QUALA_MAIL: 'Quala',\n            R2MAIL2: 'R2Mail2',\n            RAINLOOP: 'RainLoop',\n            ROUNDCUBE: 'Roundcube Webmail',\n            SAMSUNG_EMAIL: 'SamsungEmail',\n            SPARK_MAIL: 'SparkDesktop',\n            SPARROW: 'Sparrow',\n            SPICEBIRD: 'Spicebird',\n            SQUIRRELMAIL: 'SquirrelMail',\n            SYLPHEED: 'Sylpheed',\n            THE_BAT: 'The Bat!',\n            THUNDERBIRD: 'Thunderbird',\n            TROJITA: 'Trojita',\n            TURNPIKE: 'Turnpike',\n            TUTANOTA: 'tutanota-desktop',\n            WANDERLUST: 'Wanderlust',\n            WINDOWS_LIVE_MAIL: 'Windows-Live-Mail',\n            YAHOO_MAIL: 'Yahoo Mail',\n            YAHOO_MAIL_IOS: 'Yahoo Mail',\n            ZIMBRA: 'Zimbra',\n            ZOHO_MAIL: 'ZohoMail-Desktop'\n        },\n        Fetcher: {\n            AHREFS_SITEAUDIT: 'AhrefsSiteAudit',\n            AMAZON_NOVA_ACT: 'NovaAct',\n            ANTHROPIC_CLAUDE_USER: 'Claude-User',\n            ASANA: 'Asana',\n            BETTER_UPTIME_BOT: 'Better Uptime Bot',\n            BITLY_BOT: 'bitlybot',\n            BLUESKY: 'Bluesky',\n            BUFFER_LINKPREVIEWBOT: 'BufferLinkPreviewBot',\n            COHERE_AI: 'Cohere-AI',\n            DISCORD_BOT: 'Discordbot',\n            DUCKDUCKGO_ASSISTBOT: 'DuckAssistBot',\n            FLIPBOARD_PROXY: 'FlipboardProxy',\n            GOOGLE_CHROME_LIGHTHOUSE: 'Lighthouse',\n            GOOGLE_FEEDFETCHER: 'FeedFetcher-Google',\n            GOOGLE_GEMINI_DEEP_RESEARCH: 'Gemini-Deep-Research',\n            GOOGLE_IMAGEPROXY: 'GoogleImageProxy',\n            GOOGLE_PAGERENDERER: 'Google-PageRenderer',\n            GOOGLE_READ_ALOUD: 'Google-Read-Aloud',\n            GOOGLE_PRODUCER: 'GoogleProducer',\n            GOOGLE_SITE_VERIFICATION: 'Google-Site-Verification',\n            HUBSPOT_PAGE_FETCHER: 'HubSpot Page Fetcher',\n            IFRAMELY: 'Iframely',\n            KAKAOTALK_SCRAP: 'kakaotalk-scrap',\n            KEYBASE_BOT: 'KeybaseBot',\n            META_EXTERNALFETCHER: 'meta-externalfetcher',\n            META_WHATSAPP: 'WhatsApp',\n            MICROSOFT_BINGPREVIEW: 'BingPreview',\n            MICROSOFT_PREVIEW: 'MicrosoftPreview',\n            MISTRALAI_USER: 'MistralAI-User',\n            NAVER_BLUENO: 'Blueno',\n            ONCRAWL_ROGERBOT: 'rogerbot',\n            OPENAI_CHATGPT_USER: 'ChatGPT-User',\n            PERPLEXITY_USER: 'Perplexity-User',\n            PINTEREST_BOT: 'Pinterestbot',\n            SEMRUSH_SITEAUDITBOT: 'SiteAuditBot',\n            SLACK_BOT: 'Slackbot',\n            SLACK_BOT_LINKEXPANDING: 'Slackbot-LinkExpanding',\n            SLACK_IMGPROXY: 'Slack-ImgProxy',\n            SNAP_URL_PREVIEW: 'Snap URL Preview',\n            SKYPE_URIPREVIEW: 'SkypeUriPreview',\n            TELEGRAM_BOT: 'TelegramBot',\n            UPTIMEROBOT: 'UptimeRobot',\n            VERCEL_FAVICON_BOT: 'vercel-favicon-bot',\n            VERCEL_SCREENSHOT_BOT: 'vercel-screenshot-bot',\n            VERCEL_BOT: 'Vercelbot',\n            VERCEL_FLAGS: 'vercelflags',\n            VERCEL_TRACING: 'verceltracing',\n            X_TWITTERBOT: 'Twitterbot',\n            YANDEX_CALENDAR: 'YandexCalendar',\n            YANDEX_DIRECT: 'YandexDirect',\n            YANDEX_DIRECTDYN: 'YandexDirectDyn',\n            YANDEX_DIRECTFETCHER: 'YaDirectFetcher',\n            YANDEX_FORDOMAIN: 'YandexForDomain',\n            YANDEX_PAGECHECKER: 'YandexPagechecker',\n            YANDEX_SEARCHSHOP: 'YandexSearchShop',\n            YANDEX_SITELINKS: 'YandexSitelinks',\n            YANDEX_USERPROXY: 'YandexUserproxy',\n            ZOOMINFO_BOT: 'Zoombot'\n        },\n        InApp: {\n            DISCORD: 'Discord',\n            EVERNOTE: 'Evernote',\n            FIGMA: 'Figma',\n            FLIPBOARD: 'Flipboard',\n            MATTERMOST: 'Mattermost',\n            TEAMS: 'Teams',\n            NOTION: 'Notion',\n            POSTMAN: 'Postman',\n            RAMBOX: 'Rambox',\n            ROCKETCHAT: 'Rocket.Chat',\n            SLACK: 'Slack',\n            TIKTOK_LITE: 'TikTok Lite',\n            VSCODE: 'VS Code',\n            YAHOO_JAPAN: 'Yahoo! Japan'\n        },\n        Library: {\n            ADOBE_AIR: 'AdobeAIR',\n            AIOHTTP: 'aiohttp',\n            APACHE_HTTPCLIENT: 'Apache-HttpClient',\n            AXIOS: 'axios',\n            BUN: 'Bun',\n            DART: 'Dart',\n            DENO: 'Deno',\n            GO_HTTP_CLIENT: 'go-http-client',\n            GOT: 'got',\n            GUZZLEHTTP: 'GuzzleHttp',\n            HACKNEY: 'hackney',\n            HTTP_RB: 'http.rb',\n            JAVA: 'Java',\n            JAVA_HTTPCLIENT: 'Java-http-client',\n            JETTY: 'Jetty',\n            JSDOM: 'jsdom',\n            LIBWWW_PERL: 'libwww-perl',\n            LUA_RESTY_HTTP: 'lua-resty-http',\n            NEEDLE: 'Needle',\n            NUTCH: 'Nutch',\n            NODE_FETCH: 'node-fetch',\n            NODE_JS: 'Node.js',\n            NODE_SUPERAGENT: 'node-superagent',\n            OKHTTP: 'OkHttp',\n            OCAML_COHTTP: 'ocaml-cohttp',\n            PHP_SOAP: 'PHP-SOAP',\n            POSTMAN_RUNTIME: 'PostmanRuntime',\n            PYTHON_HTTPX: 'python-httpx',\n            PYTHON_URLLIB: 'python-urllib',\n            PYTHON_URLLIB3: 'python-urllib3',\n            PYTHON_REQUESTS: 'python-requests',\n            REST_CLIENT: 'rest-client',\n            SCRAPY: 'Scrapy',\n            UNDICI: 'undici'\n        }\n    },\n    DeviceVendor: {\n        Vehicle: {\n            BMW: 'BMW',\n            BYD: 'BYD',\n            JEEP: 'Jeep',\n            RIVIAN: 'Rivian',\n            TESLA: 'Tesla',\n            VOLVO: 'Volvo'\n        }\n    }\n});\n\nexport { \n    Browser,// deprecated\n    CPU,    // deprecated\n    Device, // deprecated\n    Vendor, // deprecated\n    Engine, // deprecated\n    OS,     // deprecated\n    BrowserName,\n    BrowserType, \n    CPUArch,\n    DeviceType, \n    DeviceVendor,\n    EngineName,\n    OSName,\n    Extension\n};"
  },
  {
    "path": "src/extensions/ua-parser-extensions.d.ts",
    "content": "// Type definitions for Helpers submodule of UAParser.js v2.0.9\n// Project: https://github.com/faisalman/ua-parser-js\n// Definitions by: Faisal Salman <https://github.com/faisalman>\n\nimport type { UAParserExt } from \"../main/ua-parser\";\n\nexport const Bots: UAParserExt;\nexport const CLIs: UAParserExt;\nexport const Crawlers: UAParserExt;\nexport const ExtraDevices: UAParserExt;\nexport const Emails: UAParserExt;\nexport const Fetchers: UAParserExt;\nexport const InApps: UAParserExt;\nexport const Libraries: UAParserExt;\nexport const MediaPlayers: UAParserExt;\nexport const Vehicles: UAParserExt;"
  },
  {
    "path": "src/extensions/ua-parser-extensions.js",
    "content": "///////////////////////////////////////////////\n/*  Extensions for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst MODEL     = 'model';\nconst NAME      = 'name';\nconst TYPE      = 'type';\nconst VENDOR    = 'vendor';\nconst VERSION   = 'version';\nconst MOBILE    = 'mobile';\nconst TABLET    = 'tablet';\nconst CRAWLER   = 'crawler';\nconst CLI       = 'cli';\nconst EMAIL     = 'email';\nconst FETCHER   = 'fetcher';\nconst INAPP     = 'inapp';\nconst MEDIAPLAYER = 'mediaplayer';\nconst LIBRARY    = 'library';\n\n// Helper to normalize specific email client names\nconst normalizeEmailName = function (str) {\n    const map = {\n        'YahooMobile': 'Yahoo Mail',\n        'YahooMail': 'Yahoo Mail',\n        'K-9': 'K-9 Mail',\n        'K-9 Mail': 'K-9 Mail',\n        'Zdesktop': 'Zimbra',\n        'zdesktop': 'Zimbra'\n    };\n    return map[str] || str;\n};\n\n//////////////////////\n// COMMAND LINE APPS\n/////////////////////\n\nconst CLIs = Object.freeze({\n    browser : [\n        // wget / curl / Lynx / ELinks / HTTPie / PowerShell\n        [/(wget|curl|lynx|elinks|httpie|powershell)[\\/ ]\\(?([\\w\\.-]+)/i], [NAME, VERSION, [TYPE, CLI]]\n    ]\n});\n\n////////////////////////\n// CRAWLERS / SPIDERS\n///////////////////////\n\nconst Crawlers = Object.freeze({\n    browser : [\n        [\n            // AhrefsBot - https://ahrefs.com/robot\n            // Amazonbot - https://developer.amazon.com/amazonbot\n            // Awario - https://awario.com/bots.html\n            // Bingbot / AdIdxBot - https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0\n            // Bravebot - https://search.brave.com/help/brave-search-crawler\n            // CCBot - https://commoncrawl.org/faq\n            // contxbot - https://affiliate-program.amazon.com/help/node/topic/GT98G5PPRERNVZ2C\n            // Coveobot - https://connect.coveo.com/s/article/19648\n            // CriteoBot - https://www.criteo.com/criteo-crawler/\n            // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot\n            // DuckDuckBot - http://duckduckgo.com/duckduckbot.html\n            // FacebookBot - https://developers.facebook.com/docs/sharing/bot/\n            // GPTBot - https://platform.openai.com/docs/gptbot\n            // iAskBot - https://iask.ai\n            // Kagibot - https://kagi.com/bot\n            // Kangaroo Bot - https://kangaroollm.com.au/kangaroo-bot/\n            // LinkedInBot - http://www.linkedin.com\n            // MJ12bot - https://mj12bot.com/\n            // MojeekBot - https://www.mojeek.com/bot.html\n            // Onespot - https://www.onespot.com/identifying-traffic.html\n            // OpenAI's SearchGPT - https://platform.openai.com/docs/bots\n            // PerplexityBot - https://perplexity.ai/perplexitybot\n            // SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/\n            // SeznamBot - http://napoveda.seznam.cz/seznambot-intro\n            // SurdotlyBot - http://sur.ly/bot.html\n            // Swiftbot - https://swiftype.com/swiftbot\n            // YepBot - https://yep.com/yepbot/\n            /((?:adidx|ahrefs|amazon|awario(?:smart|rss)?|bing|brave|cc|contx|coveo|criteo|dot|duckduck(?:go-favicons-)?|exa|facebook|gpt|iask|kagi|kangaroo |linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|sbintuitions|semrush|seznam|surdotly|swift|yep)bot)\\/([\\w\\.-]+)/i,\n\n            // Algolia Crawler\n            /(algolia crawler(?: renderscript)?)\\/?([\\w\\.]*)/i,\n\n            // Applebot - http://apple.com/go/applebot\n            /(applebot(?:-extended)?)\\/?([\\w\\.]*)/i,\n\n            // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001\n            /(baiduspider[-imagevdonwsfcpr]{0,7})\\/?([\\w\\.]*)/i,\n\n            // ClaudeBot (Anthropic)\n            /(claude(?:bot|-searchbot|-web)|anthropic-ai)\\/?([\\w\\.]*)/i, \n\n            // Coc Coc Bot - https://help.coccoc.com/en/search-engine\n            /(coccocbot-(?:image|web))\\/([\\w\\.]+)/i, \n\n            // Daum / HubSpot Crawler\n            /(daum(?:oa)?(?:-image)?|hubspot crawler)[ \\/]([\\w\\.]+)/i,\n\n            // Facebook / Meta \n            // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers\n            /(facebook(?:externalhit|catalog)|meta-(?:externalagent|externalads|webindexer))\\/([\\w\\.]+)/i,\n\n            // Googlebot - http://www.google.com/bot.html\n            /(google(?:bot|other|-inspectiontool)(?:-image|-video|-news)?|storebot-google)\\/?([\\w\\.]*)/i, \n\n            // Internet Archive (archive.org)\n            /(ia_archiver|archive\\.org_bot)\\/?([\\w\\.]*)/i,\n\n            // OnCrawl\n            /(oncrawl) mobile\\/([\\w\\.]+)/i,\n\n            // Qwantbot - https://help.qwant.com/bot\n            /(qwantbot(?:-news)?)[-\\w]*\\/?([\\w\\.]*)/i,\n\n            // SemrushBot - http://www.semrush.com/bot.html\n            /((?:semrush|splitsignal)bot[-abcfimostw]*)\\/?([\\w\\.-]*)/i,\n\n            // Sogou Spider\n            /(sogou (?:pic|head|web|orion|news) spider)\\/([\\w\\.]+)/i, \n\n            // Yahoo! Japan - https://support.yahoo-net.jp/PccSearch/s/article/H000007955\n            /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\\/([\\w\\.]+)/i, \n\n            // Yandex Bots - https://yandex.com/bots\n            /(yandex(?:(?:mobile)?(?:accessibility|additional|com|renderresources|screenshot|sprav)?bot(?!.+mirror)|image(?:s|resizer)|adnet|blogs|favicons|market|media|metrika|news|ontodb(?:api)?|partner|rca|tracker|turbo|verti(?:cal)?s|webmaster|video(?:parser)?))\\/([\\w\\.]+)/i,\n\n            // Yeti (Naver)\n            /(yeti)\\/([\\w\\.]+)/i,\n\n            // aiHitBot / Algolia Crawler / Audisto Crawler / BLEXBot / BrightEdge Crawler / Cloudflare AutoRAG / Diffbot / FirecrawlAgent / HuggingFace-Bot / Linespider / MSNBot / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / PanguBot / Replicate-Bot / RunPod-Bot / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / Together-Bot / VelenPublicWebCrawler / xAI-Bot / YisouSpider / YouBot / ZumBot\n            // Cotoyogi - https://ds.rois.ac.jp/en_center8/en_crawler/\n            // Freespoke - https://docs.freespoke.com/search/bot/\n            /((?:aihit|blex|diff|huggingface-|msn|pangu|replicate-|runpod-|timpi|together-|xai-|you|zum)bot|(?:audisto |brightedge |magpie-|velenpublicweb)crawler|(?:chatglm-|line|screaming frog seo |yisou)spider|cloudflare-autorag|cotoyogi|(?:firecrawl|twin)agent|freespoke|omgili(?:bot)?|openai image downloader|startpageprivateimageproxy|webzio-extended)\\/?([\\w\\.]*)/i\n        ],\n        [NAME, VERSION, [TYPE, CRAWLER]],\n\n        [\n            // Headline - https://headline.com/legal/crawler\n            /(ev-crawler)\\/([\\w\\.]+)/i\n        ],\n        [[NAME, 'Headline'], VERSION, [TYPE, CRAWLER]],\n\n        [\n            // YandexBot MirrorDetector\n            /(yandexbot\\/([\\w\\.]+); mirrordetector)/i\n        ],\n        [[NAME, /\\/.+;/ig, ''], VERSION, [TYPE, CRAWLER]],\n\n        [\n            // Google Bots\n            /((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|notebooklm|safety))/i,\n\n            // AI2Bot - https://allenai.org/crawler\n            // DataForSeoBot - https://dataforseo.com/dataforseo-bot\n            // Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot\n            // ImagesiftBot - https://imagesift.com/about\n            // Siteimprove - https://help.siteimprove.com/support/solutions/articles/80000448553\n            // TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html\n            // v0bot - https://vercel.com/docs/bot-management\n            // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp\n            // Botify / Bytespider / DeepSeekBot / Qihoo 360Spider / SeekportBot / TikTokSpider\n            /\\b((ai2|aspiegel|atlassian-|dataforseo|deepseek|imagesift|petal|seekport|turnitin|v0|yacy)bot|360spider-?(image|video)?|baidu-ads|botify|(byte|tiktok)spider|cohere-training-data-crawler|elastic(?=\\/s)|marginalia|proximic|siteimprove(?=bot|\\.com)|teoma|webzio|yahoo! slurp)/i\n        ], \n        [NAME, [TYPE, CRAWLER]]\n    ]\n});\n\n//////////////////\n// EXTRA DEVICES\n/////////////////\n\nconst ExtraDevices = Object.freeze({\n    device : [[    \n        /(nook)[\\w ]+build\\/(\\w+)/i,                                        // Nook\n        /(dell) (strea[kpr\\d ]*[\\dko])/i,                                   // Dell Streak\n        /(le[- ]+pan)[- ]+(\\w{1,9}) bui/i,                                  // Le Pan Tablets\n        /(trinity)[- ]*(t\\d{3}) bui/i,                                      // Trinity Tablets\n        /(gigaset)[- ]+(q\\w{1,9}) bui/i,                                    // Gigaset Tablets\n        /(vodafone) ([\\w ]+)(?:\\)| bui)/i                                   // Vodafone\n        ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n        /(u304aa)/i                                                         // AT&T\n        ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n\n        /\\bsie-(\\w*)/i                                                      // Siemens\n        ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n\n        /\\b(rct\\w+) b/i                                                     // RCA Tablets\n        ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n\n        /\\b(venue[\\d ]{2,7}) b/i                                            // Dell Venue Tablets\n        ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n\n        /\\b(q(?:mv|ta)\\w+) b/i                                              // Verizon Tablet\n        ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n\n        /\\b(?:barnes[& ]+noble |bn[rt])([\\w\\+ ]*) b/i                       // Barnes & Noble Tablet\n        ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n\n        /\\b(tm\\d{3}\\w+) b/i\n        ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n\n        /\\b(k88) b/i                                                        // ZTE K Series Tablet\n        ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n\n        /\\b(nx\\d{3}j) b/i                                                   // ZTE Nubia\n        ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n\n        /\\b(gen\\d{3}) b.+49h/i                                              // Swiss GEN Mobile\n        ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n\n        /\\b(zur\\d{3}) b/i                                                   // Swiss ZUR Tablet\n        ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n\n        /^((zeki)?tb.*\\b) b/i                                               // Zeki Tablets\n        ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n\n        /\\b([yr]\\d{2}) b/i,\n        /\\b(?:dragon[- ]+touch |dt)(\\w{5}) b/i                              // Dragon Touch Tablet\n        ], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [\n\n        /\\b(ns-?\\w{0,9}) b/i                                                // Insignia Tablets\n        ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n\n        /\\b((nxa|next)-?\\w{0,9}) b/i                                        // NextBook Tablets\n        ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n\n        /\\b(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i                  // Voice Xtreme Phones\n        ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [\n\n        /\\b(lvtel\\-)?(v1[12]) b/i                                           // LvTel Phones\n        ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n\n        /\\b(ph-1) /i                                                        // Essential PH-1\n        ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [\n\n        /\\b(v(100md|700na|7011|917g).*\\b) b/i                               // Envizen Tablets\n        ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n\n        /\\b(trio[-\\w\\. ]+) b/i                                              // MachSpeed Tablets\n        ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n\n        /\\btu_(1491) b/i                                                    // Rotor Tablets\n        ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]]\n    ]\n});\n\n//////////////\n// EMAIL APPS\n//////////////\n\nconst Emails = Object.freeze({\n    browser : [\n        // 1. Specific Android Mail Rule\n        [/(android)\\/([\\w\\.-]+email)/i], \n        [NAME, VERSION, [TYPE, EMAIL]], \n\n        // 2. Standard Email Clients\n        [\n            new RegExp(\n                '(' +\n                // Clients ending in 'mail' (Case 1: Prefix + optional space + [e]mail)\n                // Covers: AirMail, Claws Mail, FairEmail, SamsungEmail, Yahoo Mail, etc.\n                '(?:air|aqua|blue|claws|daum|fair|fox|k-9|mac|nylas|pegasus|poco|poly|proton|samsung|squirrel|yahoo) ?e?mail(?:-desktop| app| bridge)?|' +\n                // Standalone / Specific Names\n                'microsoft outlook|r2mail2|spicebird|turnpike|yahoomobile|' +\n                // Microsoft & Outlook Variants\n                '(?:microsoft )?outlook(?:-express)?|macoutlook|windows-live-mail|' +\n                // Specific Clients\n                'alpine|balsa|barca|canary|emclient|eudora|evolution|geary|gnus|' +\n                'horde::imp|incredimail|kmail2?|kontact|lotus-notes|' +\n                'mail(?:bird|mate|spring)|mutt|navermailapp|newton|nine|postbox|' +\n                'rainloop|roundcube webmail|spar(?:row|kdesktop)|sylpheed|' +\n                'the bat!|thunderbird|trojita|tutanota-desktop|wanderlust|' +\n                'zdesktop|zohomail-desktop' +\n                ')' +\n                // Separator\n                '(?:m.+ail; |[\\\\/ ])' +\n                // Version (Updated to allow hyphens for Turnpike)\n                '([\\\\w\\\\.-]+)', \n                'i'\n            )\n        ], \n        [\n            [NAME, normalizeEmailName], \n            VERSION, \n            [TYPE, EMAIL]\n        ],\n\n        // 3. Apple Mail Context\n        [/(mail)\\/([\\w\\.]+) cf/i], \n        [NAME, VERSION, [TYPE, EMAIL]],\n        \n        // 4. Zimbra Server\n        [/(zimbra)\\/([\\w\\.-]+)/i], \n        [NAME, VERSION, [TYPE, EMAIL]]\n    ]\n});\n\n///////////////////////\n// ON-DEMAND SCRAPERS\n//////////////////////\n\nconst Fetchers = Object.freeze({\n    browser : [\n        [\n            // Asana / Bitlybot / Better Uptime / BingPreview / Blueno / Cohere-AI / HubSpot Page Fetcher / kakaotalk-scrap / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot / WhatsApp\n            // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit\n            // Buffer Link Preview Bot - https://scraper.buffer.com/about/bots/link-preview-bot\n            // ChatGPT-User - https://platform.openai.com/docs/plugins/bot\n            // DuckAssistBot - https://duckduckgo.com/duckassistbot/\n            // Feedly - https://feedly.com/fetcher.html\n            // FlipboardProxy - https://about.flipboard.com/proxy-service/\n            // Google Site Verifier / Meta / Yahoo! Japan\n            // Iframely - https://iframely.com/docs/about\n            // Perplexity-User - https://docs.perplexity.ai/guides/bots\n            // MistralAI-User - https://docs.mistral.ai/robots/\n            // Yandex Bots - https://yandex.com/bots\n            /(asana|ahrefssiteaudit|(?:bing|microsoft)preview|blueno|(?:chatgpt|claude|mistralai|perplexity)-user|cohere-ai|flipboardproxy|hubspot page fetcher|mastodon|(?:bitly|bufferlinkpreview|discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptime(?:ro)?|zoom)bot|google-site-verification|iframely|kakaotalk-scrap|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|fordomain|pagechecker|searchshop)|yadirectfetcher|whatsapp)\\/([\\w\\.]+)/i,\n\n            // Bluesky\n            /(bluesky) cardyb\\/([\\w\\.]+)/i,\n\n            // Feedly\n            /(feedly)(?:bot)?\\/([\\w\\.]+)/i,\n\n            // Nova Act - https://github.com/aws/nova-act\n            /agent-(novaact)\\/([\\w\\.]+)/i,\n\n            // Skype\n            /(skypeuripreview) preview\\/([\\w\\.]+)/i,\n\n            // Slackbot - https://api.slack.com/robots\n            /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\\w\\.]+)/i\n        ], \n        [NAME, VERSION, [TYPE, FETCHER]],\n\n        [\n            // Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / KeybaseBot / Snapchat / Vercelbot / Yandex Bots\n            /((?:better uptime |keybase|telegram|vercel)bot|lighthouse$|feedfetcher-google|gemini-deep-research|google(?:docs|imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|vercel(flags|tracing|-(favicon|screenshot)-bot)|virustotal(?=cloud)|yandex(?:sitelinks|userproxy))/i\n        ], \n        [NAME, [TYPE, FETCHER]],\n    ],\n\n    os : [\n        [/whatsapp\\/[\\d\\.]+ (a|i)/i],\n        [[NAME, os => os == 'A' ? 'Android' : 'iOS' ]]\n    ]\n});\n\n////////////////////\n// IN-APP BROWSERS\n///////////////////\n\nconst InApps = Object.freeze({\n    browser : [[\n        // Discord/Figma/Flipboard/Mattermost/Notion/Postman/Rambox/Rocket.Chat/Slack/Teams\n        /\\b(discord|figma|mattermost|notion|postman|rambox|rocket.chat|slack|teams)\\/([\\w\\.]+).+(electron\\/|; ios)/i,\n        /(flipboard)\\/([\\w\\.]+)/i\n        ], [NAME, VERSION, [TYPE, INAPP]], [\n\n        // Evernote/Teams on mobile\n        /(evernote) win/i,\n        /(teams)mobile-(ios|and)/i\n        ], [NAME, [TYPE, INAPP]], [\n\n        // Slack\n        /chatlyio\\/([\\d\\.]+)/i], \n        [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], [\n\n        // TikTok Lite\n        /ultralite app_version\\/([\\w\\.]+)/i], \n        [VERSION, [NAME, 'TikTok Lite'], [TYPE, INAPP]], [\n\n        // VS Code\n        /\\) code\\/([\\d\\.]+).+electron\\//i], \n        [VERSION, [NAME, 'VS Code'], [TYPE, INAPP]], [\n\n        // Yahoo! Japan\n        /jp\\.co\\.yahoo\\.(?:android\\.yjtop|ipn\\.appli)\\/([\\d\\.]+)/i], \n        [VERSION, [NAME, 'Yahoo! Japan'], [TYPE, INAPP]]\n    ]\n});\n\n//////////////////////\n// MEDIA PLAYER APPS\n/////////////////////\n\nconst MediaPlayers = Object.freeze({\n    browser : [[\n        /(apple(?:coremedia|tv))\\/([\\w\\._]+)/i,                             // Generic Apple CoreMedia\n        /(coremedia) v([\\w\\._]+)/i,         \n                                                                            // Ares/Nexplayer/OSSProxy\n        /(ares|clementine|music player daemon|nexplayer|ossproxy) ([\\w\\.-]+)/i, \n                                                                            // Aqualung/Lyssna/BSPlayer/Clementine/MPD\n                                                                            // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/GnomeMplayer/MoC\n                                                                            // NSPlayer/PSP-InternetRadioPlayer/Videos\n                                                                            // Nero Home/Nero Scout/Nokia\n                                                                            // QuickTime/RealMedia/RadioApp/RadioClientApplication/\n                                                                            // SoundTap/Totem/Stagefright/Streamium\n                                                                            // XBMC/gvfs/Xine/XMMS/irapp\n        /^(aqualung|audacious|audimusicstream|amarok|bass|bsplayer|core|gnomemplayer|gvfs|irapp|lyssna|music on console|nero (?:home|scout)|nokia\\d+|nsplayer|psp-internetradioplayer|quicktime|rma|radioapp|radioclientapplication|soundtap|stagefright|streamium|totem|videos|xbmc|xine|xmms)\\/([\\w\\.-]+)/i,\n        /(lg player|nexplayer) ([\\d\\.]+)/i,\n        /player\\/(nexplayer|lg player) ([\\w\\.-]+)/i,                        // NexPlayer/LG Player\n        /(gstreamer) souphttpsrc.+libsoup\\/([\\w\\.-]+)/i,                    // Gstreamer\n        /(htc streaming player) [\\w_]+ \\/ ([\\d\\.]+)/i,                      // HTC Streaming Player\n        /(lavf)([\\d\\.]+)/i,                                                 // Lavf (FFMPEG)\n                                                                            // MPlayer SVN\n        /(mplayer)(?: |\\/)(?:(?:sherpya-){0,1}svn)(?:-| )(r\\d+(?:-\\d+[\\w\\.-]+))/i,\n        / (songbird)\\/([\\w\\.-]+)/i,                                         // Songbird/Philips-Songbird\n        /(winamp)(?:3 version|mpeg| ) ([\\w\\.-]+)/i,                         // Winamp\n        /(vlc)(?:\\/| media player - version )([\\w\\.-]+)/i,                  // VLC Videolan\n        /^(foobar2000|itunes|smp)\\/([\\d\\.]+)/i,                             // Foobar2000/iTunes/SMP\n        /com\\.(riseupradioalarm)\\/([\\d\\.]*)/i,                              // RiseUP Radio Alarm\n        /(mplayer)(?:\\s|\\/| unknown-)([\\w\\.\\-]+)/i,                         // MPlayer\n                                                                            // Windows Media Server\n        /(windows)\\/([\\w\\.-]+) upnp\\/[\\d\\.]+ dlnadoc\\/[\\d\\.]+ home media server/i\n        ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [\n\n        /(flrp)\\/([\\w\\.-]+)/i                                               // Flip Player\n        ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [\n                                                                            // FStream/NativeHost/QuerySeekSpider\n                                                                            // MPlayer (no other info)/Media Player Classic/Nero ShowTime\n                                                                            // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info)\n                                                                            // inlight radio / YourMuze\n        /(fstream|media player classic|inlight radio|mplayer|nativehost|nero showtime|ocms-bot|queryseekspider|tapinradio|tunein radio|winamp|yourmuze)/i                                                                          \n        ], [NAME, [TYPE, MEDIAPLAYER]], [\n\n        /(htc_one_s|windows-media-player|wmplayer)\\/([\\w\\.-]+)/i,           // HTC One S / Windows Media Player\n        ], [[NAME, /[_-]/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [\n\n        /(rad.io|radio.(?:de|at|fr)) ([\\d\\.]+)/i                            // Rad.io\n        ], [[NAME, 'rad.io'], VERSION, [TYPE, MEDIAPLAYER]]\n    ]\n});\n\n/////////////\n// LIBRARIES\n//////////////\n\nconst Libraries = Object.freeze({\n    browser : [\n        [\n            // Apache-HttpClient/Axios/Bun/Dart/go-http-client/got/GuzzleHttp/hackney/http.rb/Java[-HttpClient]/Jetty/jsdom/libwww-perl/lua-resty-http/Needle/Node.js/node-fetch/ocaml-cohttp/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/rest-client/Scrapy/superagent\n            /^((?:apache|go|java)-http-?client|axios|bun|dart|deno|got|(?:guzzle|lua-resty-|ocaml-co|ok)http|hackney|http\\.rb|java|jetty|libwww-perl|needle|node(?:\\.js|-fetch|-superagent)|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|rest-client|scrapy)\\/([\\w\\.]+)/i,\n            /(adobeair|aiohttp|jsdom)\\/([\\w\\.]+)/i,\n            /(nutch)-([\\w\\.-]+)(\\(|$)/i,\n            /\\((java)\\/([\\w\\.]+)/i\n        ], [NAME, VERSION, [TYPE, LIBRARY]], [\n            /(node-fetch|phpcrawl|undici)/i\n        ], [NAME, [TYPE, LIBRARY]]\n    ]\n});\n\n/////////////\n// VEHICLES\n////////////\n\nconst Vehicles = Object.freeze({\n    device : [\n        [/aftlbt962e2/i],                                                   // BMW\n        [[VENDOR, 'BMW']],\n\n        [/dilink.+(byd) auto/i],                                            // BYD\n        [VENDOR],\n\n        [/aftlft962x3/i],                                                   // Jeep\n        [[VENDOR, 'Jeep'], [MODEL, 'Wagooner']],\n        \n        [/(rivian) (r1t)/i],                                                // Rivian\n        [VENDOR, MODEL],\n\n        [/vcc.+netfront/i],                                                 // Volvo\n        [[VENDOR, 'Volvo']]\n    ]\n});\n\n//////////\n// BOTS\n/////////\n\nconst Bots = Object.freeze({\n    browser : [\n        ...CLIs.browser,\n        ...Fetchers.browser,\n        ...Crawlers.browser,\n        ...Libraries.browser\n    ],\n    os : [\n        ...Fetchers.os\n    ]\n});\n\nmodule.exports = { \n    Bots,\n    CLIs,\n    Crawlers,\n    ExtraDevices,\n    Emails,\n    Fetchers,\n    InApps,\n    Libraries,\n    MediaPlayers,\n    Vehicles\n};\n"
  },
  {
    "path": "src/extensions/ua-parser-extensions.mjs",
    "content": "// Generated ESM version of ua-parser-js/extensions\n// DO NOT EDIT THIS FILE!\n// Source: /src/extensions/ua-parser-extensions.js\n\n///////////////////////////////////////////////\n/*  Extensions for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst MODEL     = 'model';\nconst NAME      = 'name';\nconst TYPE      = 'type';\nconst VENDOR    = 'vendor';\nconst VERSION   = 'version';\nconst MOBILE    = 'mobile';\nconst TABLET    = 'tablet';\nconst CRAWLER   = 'crawler';\nconst CLI       = 'cli';\nconst EMAIL     = 'email';\nconst FETCHER   = 'fetcher';\nconst INAPP     = 'inapp';\nconst MEDIAPLAYER = 'mediaplayer';\nconst LIBRARY    = 'library';\n\n// Helper to normalize specific email client names\nconst normalizeEmailName = function (str) {\n    const map = {\n        'YahooMobile': 'Yahoo Mail',\n        'YahooMail': 'Yahoo Mail',\n        'K-9': 'K-9 Mail',\n        'K-9 Mail': 'K-9 Mail',\n        'Zdesktop': 'Zimbra',\n        'zdesktop': 'Zimbra'\n    };\n    return map[str] || str;\n};\n\n//////////////////////\n// COMMAND LINE APPS\n/////////////////////\n\nconst CLIs = Object.freeze({\n    browser : [\n        // wget / curl / Lynx / ELinks / HTTPie / PowerShell\n        [/(wget|curl|lynx|elinks|httpie|powershell)[\\/ ]\\(?([\\w\\.-]+)/i], [NAME, VERSION, [TYPE, CLI]]\n    ]\n});\n\n////////////////////////\n// CRAWLERS / SPIDERS\n///////////////////////\n\nconst Crawlers = Object.freeze({\n    browser : [\n        [\n            // AhrefsBot - https://ahrefs.com/robot\n            // Amazonbot - https://developer.amazon.com/amazonbot\n            // Bingbot / AdIdxBot - https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0\n            // Bravebot - https://search.brave.com/help/brave-search-crawler\n            // CCBot - https://commoncrawl.org/faq\n            // contxbot - https://affiliate-program.amazon.com/help/node/topic/GT98G5PPRERNVZ2C\n            // Coveobot - https://connect.coveo.com/s/article/19648\n            // CriteoBot - https://www.criteo.com/criteo-crawler/\n            // Dotbot - https://moz.com/help/moz-procedures/crawlers/dotbot\n            // DuckDuckBot - http://duckduckgo.com/duckduckbot.html\n            // FacebookBot - https://developers.facebook.com/docs/sharing/bot/\n            // GPTBot - https://platform.openai.com/docs/gptbot\n            // iAskBot - https://iask.ai\n            // Kagibot - https://kagi.com/bot\n            // Kangaroo Bot - https://kangaroollm.com.au/kangaroo-bot/\n            // LinkedInBot - http://www.linkedin.com\n            // MJ12bot - https://mj12bot.com/\n            // MojeekBot - https://www.mojeek.com/bot.html\n            // Onespot - https://www.onespot.com/identifying-traffic.html\n            // OpenAI's SearchGPT - https://platform.openai.com/docs/bots\n            // PerplexityBot - https://perplexity.ai/perplexitybot\n            // SBIntuitionsBot - https://www.sbintuitions.co.jp/bot/\n            // SeznamBot - http://napoveda.seznam.cz/seznambot-intro\n            // SurdotlyBot - http://sur.ly/bot.html\n            // Swiftbot - https://swiftype.com/swiftbot\n            // YepBot - https://yep.com/yepbot/\n            /((?:adidx|ahrefs|amazon|bing|brave|cc|contx|coveo|criteo|dot|duckduck(?:go-favicons-)?|exa|facebook|gpt|iask|kagi|kangaroo |linkedin|mj12|mojeek|oai-search|onespot-scraper|perplexity|sbintuitions|semrush|seznam|surdotly|swift|yep)bot)\\/([\\w\\.-]+)/i,\n\n            // Algolia Crawler\n            /(algolia crawler(?: renderscript)?)\\/?([\\w\\.]*)/i,\n\n            // Applebot - http://apple.com/go/applebot\n            /(applebot(?:-extended)?)\\/?([\\w\\.]*)/i,\n\n            // Baiduspider https://help.baidu.com/question?prod_id=99&class=0&id=3001\n            /(baiduspider[-imagevdonwsfcpr]{0,7})\\/?([\\w\\.]*)/i,\n\n            // ClaudeBot (Anthropic)\n            /(claude(?:bot|-searchbot|-web)|anthropic-ai)\\/?([\\w\\.]*)/i, \n\n            // Coc Coc Bot - https://help.coccoc.com/en/search-engine\n            /(coccocbot-(?:image|web))\\/([\\w\\.]+)/i, \n\n            // Daum\n            /(daum(?:oa)?(?:-image)?)[ \\/]([\\w\\.]+)/i,\n\n            // Facebook / Meta \n            // https://developers.facebook.com/docs/sharing/webmasters/web-crawlers\n            /(facebook(?:externalhit|catalog)|meta-externalagent)\\/([\\w\\.]+)/i,\n\n            // Googlebot - http://www.google.com/bot.html\n            /(google(?:bot|other|-inspectiontool)(?:-image|-video|-news)?|storebot-google)\\/?([\\w\\.]*)/i, \n\n            // Internet Archive (archive.org)\n            /(ia_archiver|archive\\.org_bot)\\/?([\\w\\.]*)/i,\n\n            // OnCrawl\n            /(oncrawl) mobile\\/([\\w\\.]+)/i,\n\n            // Qwantbot - https://help.qwant.com/bot\n            /(qwantbot(?:-news)?)[-\\w]*\\/?([\\w\\.]*)/i,\n\n            // SemrushBot - http://www.semrush.com/bot.html\n            /((?:semrush|splitsignal)bot[-abcfimostw]*)\\/?([\\w\\.-]*)/i,\n\n            // Sogou Spider\n            /(sogou (?:pic|head|web|orion|news) spider)\\/([\\w\\.]+)/i, \n\n            // Yahoo! Japan - https://support.yahoo-net.jp/PccSearch/s/article/H000007955\n            /(y!?j-(?:asr|br[uw]|dscv|mmp|vsidx|wsc))\\/([\\w\\.]+)/i, \n\n            // Yandex Bots - https://yandex.com/bots\n            /(yandex(?:(?:mobile)?(?:accessibility|additional|com|renderresources|screenshot|sprav)?bot(?!.+mirror)|image(?:s|resizer)|adnet|blogs|favicons|market|media|metrika|news|ontodb(?:api)?|partner|rca|tracker|turbo|verti(?:cal)?s|webmaster|video(?:parser)?))\\/([\\w\\.]+)/i,\n\n            // Yeti (Naver)\n            /(yeti)\\/([\\w\\.]+)/i,\n\n            // aiHitBot / Algolia Crawler / BLEXBot / Cloudflare AutoRAG / Diffbot / FirecrawlAgent / HuggingFace-Bot / Linespider / MSNBot / Magpie-Crawler / Omgilibot / OpenAI Image Downloader / PanguBot / Replicate-Bot / RunPod-Bot / Webzio-Extended / Screaming Frog SEO Spider / Startpage / Timpibot / Together-Bot / VelenPublicWebCrawler / xAI-Bot / YisouSpider / YouBot / ZumBot\n            // Cotoyogi - https://ds.rois.ac.jp/en_center8/en_crawler/\n            // Freespoke - https://docs.freespoke.com/search/bot/\n            /((?:aihit|blex|diff|huggingface-|msn|pangu|replicate-|runpod-|timpi|together-|xai-|you|zum)bot|(?:magpie-|velenpublicweb)crawler|(?:chatglm-|line|screaming frog seo |yisou)spider|cloudflare-autorag|cotoyogi|(?:firecrawl|twin)agent|freespoke|omgili(?:bot)?|openai image downloader|startpageprivateimageproxy|webzio-extended)\\/?([\\w\\.]*)/i\n        ],\n        [NAME, VERSION, [TYPE, CRAWLER]],\n\n        [\n            // YandexBot MirrorDetector\n            /(yandexbot\\/([\\w\\.]+); mirrordetector)/i\n        ],\n        [[NAME, /\\/.+;/ig, ''], VERSION, [TYPE, CRAWLER]],\n\n        [\n            // Google Bots\n            /((?:adsbot|apis|mediapartners)-google(?:-mobile)?|google-?(?:other|cloudvertexbot|extended|notebooklm|safety))/i,\n\n            // AI2Bot - https://allenai.org/crawler\n            // DataForSeoBot - https://dataforseo.com/dataforseo-bot\n            // Huawei AspiegelBot / PetalBot https://aspiegel.com/petalbot\n            // ImagesiftBot - https://imagesift.com/about\n            // Siteimprove - https://help.siteimprove.com/support/solutions/articles/80000448553\n            // TurnitinBot - https://www.turnitin.com/robot/crawlerinfo.html\n            // v0bot - https://vercel.com/docs/bot-management\n            // Yahoo! Slurp - http://help.yahoo.com/help/us/ysearch/slurp\n            // Botify / Bytespider / DeepSeekBot / Qihoo 360Spider / SeekportBot / TikTokSpider\n            /\\b((ai2|aspiegel|atlassian-|dataforseo|deepseek|imagesift|petal|seekport|turnitin|v0)bot|360spider-?(image|video)?|baidu-ads|botify|(byte|tiktok)spider|cohere-training-data-crawler|elastic(?=\\/s)|marginalia|siteimprove(?=bot|\\.com)|teoma|webzio|yahoo! slurp)/i\n        ], \n        [NAME, [TYPE, CRAWLER]]\n    ]\n});\n\n//////////////////\n// EXTRA DEVICES\n/////////////////\n\nconst ExtraDevices = Object.freeze({\n    device : [[    \n        /(nook)[\\w ]+build\\/(\\w+)/i,                                        // Nook\n        /(dell) (strea[kpr\\d ]*[\\dko])/i,                                   // Dell Streak\n        /(le[- ]+pan)[- ]+(\\w{1,9}) bui/i,                                  // Le Pan Tablets\n        /(trinity)[- ]*(t\\d{3}) bui/i,                                      // Trinity Tablets\n        /(gigaset)[- ]+(q\\w{1,9}) bui/i,                                    // Gigaset Tablets\n        /(vodafone) ([\\w ]+)(?:\\)| bui)/i                                   // Vodafone\n        ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n        /(u304aa)/i                                                         // AT&T\n        ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n\n        /\\bsie-(\\w*)/i                                                      // Siemens\n        ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n\n        /\\b(rct\\w+) b/i                                                     // RCA Tablets\n        ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n\n        /\\b(venue[\\d ]{2,7}) b/i                                            // Dell Venue Tablets\n        ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n\n        /\\b(q(?:mv|ta)\\w+) b/i                                              // Verizon Tablet\n        ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n\n        /\\b(?:barnes[& ]+noble |bn[rt])([\\w\\+ ]*) b/i                       // Barnes & Noble Tablet\n        ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n\n        /\\b(tm\\d{3}\\w+) b/i\n        ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n\n        /\\b(k88) b/i                                                        // ZTE K Series Tablet\n        ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n\n        /\\b(nx\\d{3}j) b/i                                                   // ZTE Nubia\n        ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n\n        /\\b(gen\\d{3}) b.+49h/i                                              // Swiss GEN Mobile\n        ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n\n        /\\b(zur\\d{3}) b/i                                                   // Swiss ZUR Tablet\n        ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n\n        /^((zeki)?tb.*\\b) b/i                                               // Zeki Tablets\n        ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n\n        /\\b([yr]\\d{2}) b/i,\n        /\\b(?:dragon[- ]+touch |dt)(\\w{5}) b/i                              // Dragon Touch Tablet\n        ], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [\n\n        /\\b(ns-?\\w{0,9}) b/i                                                // Insignia Tablets\n        ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n\n        /\\b((nxa|next)-?\\w{0,9}) b/i                                        // NextBook Tablets\n        ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n\n        /\\b(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i                  // Voice Xtreme Phones\n        ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [\n\n        /\\b(lvtel\\-)?(v1[12]) b/i                                           // LvTel Phones\n        ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n\n        /\\b(ph-1) /i                                                        // Essential PH-1\n        ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [\n\n        /\\b(v(100md|700na|7011|917g).*\\b) b/i                               // Envizen Tablets\n        ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n\n        /\\b(trio[-\\w\\. ]+) b/i                                              // MachSpeed Tablets\n        ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n\n        /\\btu_(1491) b/i                                                    // Rotor Tablets\n        ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]]\n    ]\n});\n\n//////////////\n// EMAIL APPS\n//////////////\n\nconst Emails = Object.freeze({\n    browser : [\n        // 1. Specific Android Mail Rule\n        [/(android)\\/([\\w\\.-]+email)/i], \n        [NAME, VERSION, [TYPE, EMAIL]], \n\n        // 2. Standard Email Clients\n        [\n            new RegExp(\n                '(' +\n                // Clients ending in 'mail' (Case 1: Prefix + optional space + [e]mail)\n                // Covers: AirMail, Claws Mail, FairEmail, SamsungEmail, Yahoo Mail, etc.\n                '(?:air|aqua|blue|claws|daum|fair|fox|k-9|mac|nylas|pegasus|poco|poly|proton|samsung|squirrel|yahoo) ?e?mail(?:-desktop| app| bridge)?|' +\n                // Standalone / Specific Names\n                'microsoft outlook|r2mail2|spicebird|turnpike|yahoomobile|' +\n                // Microsoft & Outlook Variants\n                '(?:microsoft )?outlook(?:-express)?|macoutlook|windows-live-mail|' +\n                // Specific Clients\n                'alpine|balsa|barca|canary|emclient|eudora|evolution|geary|gnus|' +\n                'horde::imp|incredimail|kmail2?|kontact|lotus-notes|' +\n                'mail(?:bird|mate|spring)|mutt|navermailapp|newton|nine|postbox|' +\n                'rainloop|roundcube webmail|spar(?:row|kdesktop)|sylpheed|' +\n                'the bat!|thunderbird|trojita|tutanota-desktop|wanderlust|' +\n                'zdesktop|zohomail-desktop' +\n                ')' +\n                // Separator\n                '(?:m.+ail; |[\\\\/ ])' +\n                // Version (Updated to allow hyphens for Turnpike)\n                '([\\\\w\\\\.-]+)', \n                'i'\n            )\n        ], \n        [\n            [NAME, normalizeEmailName], \n            VERSION, \n            [TYPE, EMAIL]\n        ],\n\n        // 3. Apple Mail Context\n        [/(mail)\\/([\\w\\.]+) cf/i], \n        [NAME, VERSION, [TYPE, EMAIL]],\n        \n        // 4. Zimbra Server\n        [/(zimbra)\\/([\\w\\.-]+)/i], \n        [NAME, VERSION, [TYPE, EMAIL]]\n    ]\n});\n\n///////////////////////\n// ON-DEMAND SCRAPERS\n//////////////////////\n\nconst Fetchers = Object.freeze({\n    browser : [\n        [\n            // Asana / Bitlybot / Better Uptime / BingPreview / Blueno / Cohere-AI / HubSpot Page Fetcher / kakaotalk-scrap / Mastodon / MicrosoftPreview / Pinterestbot / Redditbot / Rogerbot / SiteAuditBot / Telegrambot / Twitterbot / UptimeRobot / WhatsApp\n            // AhrefsSiteAudit - https://ahrefs.com/robot/site-audit\n            // Buffer Link Preview Bot - https://scraper.buffer.com/about/bots/link-preview-bot\n            // ChatGPT-User - https://platform.openai.com/docs/plugins/bot\n            // DuckAssistBot - https://duckduckgo.com/duckassistbot/\n            // FlipboardProxy - https://about.flipboard.com/proxy-service/\n            // Google Site Verifier / Meta / Yahoo! Japan\n            // Iframely - https://iframely.com/docs/about\n            // Perplexity-User - https://docs.perplexity.ai/guides/bots\n            // MistralAI-User - https://docs.mistral.ai/robots/\n            // Yandex Bots - https://yandex.com/bots\n            /(asana|ahrefssiteaudit|(?:bing|microsoft)preview|blueno|(?:chatgpt|claude|mistralai|perplexity)-user|cohere-ai|flipboardproxy|hubspot page fetcher|mastodon|(?:bitly|bufferlinkpreview|discord|duckassist|linkedin|pinterest|reddit|roger|siteaudit|twitter|uptimero|zoom)bot|google-site-verification|iframely|kakaotalk-scrap|meta-externalfetcher|y!?j-dlc|yandex(?:calendar|direct(?:dyn)?|fordomain|pagechecker|searchshop)|yadirectfetcher|whatsapp)\\/([\\w\\.]+)/i,\n\n            // Bluesky\n            /(bluesky) cardyb\\/([\\w\\.]+)/i,\n\n            // Nova Act - https://github.com/aws/nova-act\n            /agent-(novaact)\\/([\\w\\.]+)/i,\n\n            // Skype\n            /(skypeuripreview) preview\\/([\\w\\.]+)/i,\n\n            // Slackbot - https://api.slack.com/robots\n            /(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\\w\\.]+)/i\n        ], \n        [NAME, VERSION, [TYPE, FETCHER]],\n\n        [\n            // Google Bots / Chrome-Lighthouse / Gemini-Deep-Research / KeybaseBot / Snapchat / Vercelbot / Yandex Bots\n            /((?:better uptime |keybase|telegram|vercel)bot|lighthouse$|feedfetcher-google|gemini-deep-research|google(?:imageproxy|-read-aloud|-pagerenderer|producer)|snap url preview|vercel(flags|tracing|-(favicon|screenshot)-bot)|yandex(?:sitelinks|userproxy))/i\n        ], \n        [NAME, [TYPE, FETCHER]],\n    ],\n\n    os : [\n        [/whatsapp\\/[\\d\\.]+ (a|i)/i],\n        [[NAME, os => os == 'A' ? 'Android' : 'iOS' ]]\n    ]\n});\n\n////////////////////\n// IN-APP BROWSERS\n///////////////////\n\nconst InApps = Object.freeze({\n    browser : [[\n        // Discord/Figma/Flipboard/Mattermost/Notion/Postman/Rambox/Rocket.Chat/Slack/Teams\n        /\\b(discord|figma|mattermost|notion|postman|rambox|rocket.chat|slack|teams)\\/([\\w\\.]+).+(electron\\/|; ios)/i,\n        /(flipboard)\\/([\\w\\.]+)/i\n        ], [NAME, VERSION, [TYPE, INAPP]], [\n\n        // Evernote/Teams on mobile\n        /(evernote) win/i,\n        /(teams)mobile-(ios|and)/i\n        ], [NAME, [TYPE, INAPP]], [\n\n        // Slack\n        /chatlyio\\/([\\d\\.]+)/i], \n        [VERSION, [NAME, 'Slack'], [TYPE, INAPP]], [\n\n        // TikTok Lite\n        /ultralite app_version\\/([\\w\\.]+)/i], \n        [VERSION, [NAME, 'TikTok Lite'], [TYPE, INAPP]], [\n\n        // VS Code\n        /\\) code\\/([\\d\\.]+).+electron\\//i], \n        [VERSION, [NAME, 'VS Code'], [TYPE, INAPP]], [\n\n        // Yahoo! Japan\n        /jp\\.co\\.yahoo\\.(?:android\\.yjtop|ipn\\.appli)\\/([\\d\\.]+)/i], \n        [VERSION, [NAME, 'Yahoo! Japan'], [TYPE, INAPP]]\n    ]\n});\n\n//////////////////////\n// MEDIA PLAYER APPS\n/////////////////////\n\nconst MediaPlayers = Object.freeze({\n    browser : [[\n        /(apple(?:coremedia|tv))\\/([\\w\\._]+)/i,                             // Generic Apple CoreMedia\n        /(coremedia) v([\\w\\._]+)/i,         \n                                                                            // Ares/Nexplayer/OSSProxy\n        /(ares|clementine|music player daemon|nexplayer|ossproxy) ([\\w\\.-]+)/i, \n                                                                            // Aqualung/Lyssna/BSPlayer/Clementine/MPD\n                                                                            // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/GnomeMplayer/MoC\n                                                                            // NSPlayer/PSP-InternetRadioPlayer/Videos\n                                                                            // Nero Home/Nero Scout/Nokia\n                                                                            // QuickTime/RealMedia/RadioApp/RadioClientApplication/\n                                                                            // SoundTap/Totem/Stagefright/Streamium\n                                                                            // XBMC/gvfs/Xine/XMMS/irapp\n        /^(aqualung|audacious|audimusicstream|amarok|bass|bsplayer|core|gnomemplayer|gvfs|irapp|lyssna|music on console|nero (?:home|scout)|nokia\\d+|nsplayer|psp-internetradioplayer|quicktime|rma|radioapp|radioclientapplication|soundtap|stagefright|streamium|totem|videos|xbmc|xine|xmms)\\/([\\w\\.-]+)/i,\n        /(lg player|nexplayer) ([\\d\\.]+)/i,\n        /player\\/(nexplayer|lg player) ([\\w\\.-]+)/i,                        // NexPlayer/LG Player\n        /(gstreamer) souphttpsrc.+libsoup\\/([\\w\\.-]+)/i,                    // Gstreamer\n        /(htc streaming player) [\\w_]+ \\/ ([\\d\\.]+)/i,                      // HTC Streaming Player\n        /(lavf)([\\d\\.]+)/i,                                                 // Lavf (FFMPEG)\n                                                                            // MPlayer SVN\n        /(mplayer)(?: |\\/)(?:(?:sherpya-){0,1}svn)(?:-| )(r\\d+(?:-\\d+[\\w\\.-]+))/i,\n        / (songbird)\\/([\\w\\.-]+)/i,                                         // Songbird/Philips-Songbird\n        /(winamp)(?:3 version|mpeg| ) ([\\w\\.-]+)/i,                         // Winamp\n        /(vlc)(?:\\/| media player - version )([\\w\\.-]+)/i,                  // VLC Videolan\n        /^(foobar2000|itunes|smp)\\/([\\d\\.]+)/i,                             // Foobar2000/iTunes/SMP\n        /com\\.(riseupradioalarm)\\/([\\d\\.]*)/i,                              // RiseUP Radio Alarm\n        /(mplayer)(?:\\s|\\/| unknown-)([\\w\\.\\-]+)/i,                         // MPlayer\n                                                                            // Windows Media Server\n        /(windows)\\/([\\w\\.-]+) upnp\\/[\\d\\.]+ dlnadoc\\/[\\d\\.]+ home media server/i\n        ], [NAME, VERSION, [TYPE, MEDIAPLAYER]], [\n\n        /(flrp)\\/([\\w\\.-]+)/i                                               // Flip Player\n        ], [[NAME, 'Flip Player'], VERSION, [TYPE, MEDIAPLAYER]], [\n                                                                            // FStream/NativeHost/QuerySeekSpider\n                                                                            // MPlayer (no other info)/Media Player Classic/Nero ShowTime\n                                                                            // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info)\n                                                                            // inlight radio / YourMuze\n        /(fstream|media player classic|inlight radio|mplayer|nativehost|nero showtime|ocms-bot|queryseekspider|tapinradio|tunein radio|winamp|yourmuze)/i                                                                          \n        ], [NAME, [TYPE, MEDIAPLAYER]], [\n\n        /(htc_one_s|windows-media-player|wmplayer)\\/([\\w\\.-]+)/i,           // HTC One S / Windows Media Player\n        ], [[NAME, /[_-]/g, ' '], VERSION, [TYPE, MEDIAPLAYER]], [\n\n        /(rad.io|radio.(?:de|at|fr)) ([\\d\\.]+)/i                            // Rad.io\n        ], [[NAME, 'rad.io'], VERSION, [TYPE, MEDIAPLAYER]]\n    ]\n});\n\n/////////////\n// LIBRARIES\n//////////////\n\nconst Libraries = Object.freeze({\n    browser : [\n        [\n            // Apache-HttpClient/Axios/Bun/Dart/go-http-client/got/GuzzleHttp/hackney/http.rb/Java[-HttpClient]/Jetty/jsdom/libwww-perl/lua-resty-http/Needle/Node.js/node-fetch/ocaml-cohttp/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/rest-client/Scrapy/superagent\n            /^((?:apache|go|java)-http-?client|axios|bun|dart|deno|got|(?:guzzle|lua-resty-|ocaml-co|ok)http|hackney|http\\.rb|java|jetty|libwww-perl|needle|node(?:\\.js|-fetch|-superagent)|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|rest-client|scrapy)\\/([\\w\\.]+)/i,\n            /(adobeair|aiohttp|jsdom)\\/([\\w\\.]+)/i,\n            /(nutch)-([\\w\\.-]+)(\\(|$)/i,\n            /\\((java)\\/([\\w\\.]+)/i\n        ], [NAME, VERSION, [TYPE, LIBRARY]], [\n            /(node-fetch|undici)/i\n        ], [NAME, [TYPE, LIBRARY]]\n    ]\n});\n\n/////////////\n// VEHICLES\n////////////\n\nconst Vehicles = Object.freeze({\n    device : [\n        [/aftlbt962e2/i],                                                   // BMW\n        [[VENDOR, 'BMW']],\n\n        [/dilink.+(byd) auto/i],                                            // BYD\n        [VENDOR],\n\n        [/aftlft962x3/i],                                                   // Jeep\n        [[VENDOR, 'Jeep'], [MODEL, 'Wagooner']],\n        \n        [/(rivian) (r1t)/i],                                                // Rivian\n        [VENDOR, MODEL],\n\n        [/vcc.+netfront/i],                                                 // Volvo\n        [[VENDOR, 'Volvo']]\n    ]\n});\n\n//////////\n// BOTS\n/////////\n\nconst Bots = Object.freeze({\n    browser : [\n        ...CLIs.browser,\n        ...Fetchers.browser,\n        ...Crawlers.browser,\n        ...Libraries.browser\n    ],\n    os : [\n        ...Fetchers.os\n    ]\n});\n\nexport { \n    Bots,\n    CLIs,\n    Crawlers,\n    ExtraDevices,\n    Emails,\n    Fetchers,\n    InApps,\n    Libraries,\n    MediaPlayers,\n    Vehicles\n};\n"
  },
  {
    "path": "src/helpers/ua-parser-helpers.d.ts",
    "content": "// Type definitions for Helpers submodule of UAParser.js v2.0.9\n// Project: https://github.com/faisalman/ua-parser-js\n// Definitions by: Faisal Salman <https://github.com/faisalman>\n\nimport type { IResult } from \"../main/ua-parser\";\n\nexport function getOutlookEdition(name: string, version: string): string;\nexport function isFrozenUA(ua: string): boolean;\n\n/**\n * @deprecated Moved to `device-detection` submodule\n */\nexport function getDeviceVendor(model: string): string | undefined;\n/**\n * @deprecated Moved to `device-detection` submodule\n */\nexport function isAppleSilicon(resultOrUA: IResult | string): boolean;\n/**\n * @deprecated Moved to `bot-detection` submodule\n */\nexport function isAIBot(resultOrUA: IResult | string): boolean;\n/**\n * @deprecated Moved to `bot-detection` submodule\n */\nexport function isBot(resultOrUA: IResult | string): boolean;\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nexport function isChromeFamily(resultOrUA: IResult | string): boolean;\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nexport function isElectron(): boolean;\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nexport function isFromEU(): boolean;\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nexport function isStandalonePWA(): boolean;"
  },
  {
    "path": "src/helpers/ua-parser-helpers.js",
    "content": "///////////////////////////////////////////////\n/*  Helpers for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nconst { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } = require('../device-detection/device-detection');\nconst { isBot: _isBot, isAICrawler } = require('../bot-detection/bot-detection');\nconst { isChromeFamily: _isChromeFamily, isElectron: _isElectron, isStandalonePWA: _isStandalonePWA } = require('../browser-detection/browser-detection');\nconst { isFromEU: _isFromEU } = require('../browser-detection/browser-detection');\nconst { isFrozenUA } = require('ua-is-frozen');\n\n/**\n * @deprecated Moved to `device-detection` submodule\n */\nconst getDeviceVendor = _getDeviceVendor;\n\n/**\n * @deprecated Moved to `device-detection` submodule\n */\nconst isAppleSilicon = _isAppleSilicon;\n\n/**\n * @deprecated Moved to `bot-detection` submodule\n */\nconst isAIBot = isAICrawler;\n\n/**\n * @deprecated Moved to `bot-detection` submodule\n */\nconst isBot = _isBot;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isChromeFamily = _isChromeFamily;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isElectron = () => _isElectron;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isFromEU = _isFromEU;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isStandalonePWA = _isStandalonePWA;\n\n/**\n * Translates a raw Outlook User-Agent name/version into a \n * Developer-friendly Edition (e.g., \"Outlook 2019 (Modern Word)\").\n */\nconst getOutlookEdition = (name, version) => {\n    if (!name || !version) return name;\n    const cleanName = name.toLowerCase().replace(/microsoft\\s+/, '');\n    \n    // 1. Handle Mac Separately (Different Rendering Engine)\n    if (cleanName === 'macoutlook') {\n        const major = parseInt(version.split('.')[0], 10);\n        if (major >= 16) return \"Outlook for Mac (Modern)\";\n        return \"Outlook for Mac (Legacy)\";\n    }\n\n    // 2. Handle Windows Outlook\n    if (cleanName === 'outlook') {\n        const parts = version.split('.').map(Number);\n        const major = parts[0];\n        const build = parts[2] || 0; // Build number is usually the 3rd part\n\n        // Pre-2016 Versions (Clear Major Version mapping)\n        if (major === 15) return \"Outlook 2013\";\n        if (major === 14) return \"Outlook 2010\";\n        if (major === 12) return \"Outlook 2007\";\n        if (major < 12)   return \"Outlook (Legacy)\";\n\n        // The Version 16.0 Confusion\n        if (major === 16) {\n            // Build < 10000 = MSI (Volume License 2016/2019)\n            // These render poorly (No SVG, older bugs)\n            if (build < 10000) {\n                return \"Outlook 2016 (MSI / Volume License)\";\n            }\n            // Build >= 10000 = Click-to-Run (Retail 2016 / 2019 / 365)\n            // These render well (SVG support, modern CSS)\n            return \"Outlook 365 / 2019+ (Modern)\";\n        }\n    }\n\n    // 3. Fallback for 'Outlook Express' or 'New Outlook' (Browser)\n    return name;\n};\n\nmodule.exports = { \n    getDeviceVendor,\n    isAppleSilicon,\n    isAIBot,\n    isBot,\n    isChromeFamily,\n    isElectron,\n    isFromEU,\n    isFrozenUA,\n    isStandalonePWA,\n    getOutlookEdition\n}"
  },
  {
    "path": "src/helpers/ua-parser-helpers.mjs",
    "content": "// Generated ESM version of ua-parser-js/helpers\n// DO NOT EDIT THIS FILE!\n// Source: /src/helpers/ua-parser-helpers.js\n\n///////////////////////////////////////////////\n/*  Helpers for UAParser.js v2.0.9\n    https://github.com/faisalman/ua-parser-js\n    Author: Faisal Salman <f@faisalman.com>\n    AGPLv3 License */\n//////////////////////////////////////////////\n\n/*jshint esversion: 6 */ \n\nimport { getDeviceVendor as _getDeviceVendor, isAppleSilicon as _isAppleSilicon } from '../device-detection/device-detection.mjs';\nimport { isBot as _isBot, isAICrawler } from '../bot-detection/bot-detection.mjs';\nimport { isChromeFamily as _isChromeFamily, isElectron as _isElectron, isStandalonePWA as _isStandalonePWA } from '../browser-detection/browser-detection.mjs';\nimport { isFromEU as _isFromEU } from '../browser-detection/browser-detection.mjs';\nimport { isFrozenUA } from 'ua-is-frozen';\n\n/**\n * @deprecated Moved to `device-detection` submodule\n */\nconst getDeviceVendor = _getDeviceVendor;\n\n/**\n * @deprecated Moved to `device-detection` submodule\n */\nconst isAppleSilicon = _isAppleSilicon;\n\n/**\n * @deprecated Moved to `bot-detection` submodule\n */\nconst isAIBot = isAICrawler;\n\n/**\n * @deprecated Moved to `bot-detection` submodule\n */\nconst isBot = _isBot;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isChromeFamily = _isChromeFamily;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isElectron = () => _isElectron;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isFromEU = _isFromEU;\n\n/**\n * @deprecated Moved to `browser-detection` submodule\n */\nconst isStandalonePWA = _isStandalonePWA;\n\n/**\n * Translates a raw Outlook User-Agent name/version into a \n * Developer-friendly Edition (e.g., \"Outlook 2019 (Modern Word)\").\n */\nconst getOutlookEdition = (name, version) => {\n    if (!name || !version) return name;\n    const cleanName = name.toLowerCase().replace(/microsoft\\s+/, '');\n    \n    // 1. Handle Mac Separately (Different Rendering Engine)\n    if (cleanName === 'macoutlook') {\n        const major = parseInt(version.split('.')[0], 10);\n        if (major >= 16) return \"Outlook for Mac (Modern)\";\n        return \"Outlook for Mac (Legacy)\";\n    }\n\n    // 2. Handle Windows Outlook\n    if (cleanName === 'outlook') {\n        const parts = version.split('.').map(Number);\n        const major = parts[0];\n        const build = parts[2] || 0; // Build number is usually the 3rd part\n\n        // Pre-2016 Versions (Clear Major Version mapping)\n        if (major === 15) return \"Outlook 2013\";\n        if (major === 14) return \"Outlook 2010\";\n        if (major === 12) return \"Outlook 2007\";\n        if (major < 12)   return \"Outlook (Legacy)\";\n\n        // The Version 16.0 Confusion\n        if (major === 16) {\n            // Build < 10000 = MSI (Volume License 2016/2019)\n            // These render poorly (No SVG, older bugs)\n            if (build < 10000) {\n                return \"Outlook 2016 (MSI / Volume License)\";\n            }\n            // Build >= 10000 = Click-to-Run (Retail 2016 / 2019 / 365)\n            // These render well (SVG support, modern CSS)\n            return \"Outlook 365 / 2019+ (Modern)\";\n        }\n    }\n\n    // 3. Fallback for 'Outlook Express' or 'New Outlook' (Browser)\n    return name;\n};\n\nexport { \n    getDeviceVendor,\n    isAppleSilicon,\n    isAIBot,\n    isBot,\n    isChromeFamily,\n    isElectron,\n    isFromEU,\n    isFrozenUA,\n    isStandalonePWA,\n    getOutlookEdition\n}"
  },
  {
    "path": "src/main/ua-parser.d.ts",
    "content": "// Type definitions for UAParser.js v2.0.9\n// Project: https://github.com/faisalman/ua-parser-js\n// Definitions by: Faisal Salman <https://github.com/faisalman>\n\nimport { BrowserType, CPUArch, DeviceType, EngineName } from \"../enums/ua-parser-enums\";\n\ndeclare namespace UAParser {\n    \n    interface IData<T> {\n        is(val: string): boolean;\n        toString(): string;\n        withClientHints(): PromiseLike<T> | T;\n        withFeatureCheck(): PromiseLike<T> | T;\n    }\n\n    interface IBrowser extends IData<IBrowser> {\n        name?: string;\n        version?: string;\n        major?: string;\n        type?: typeof BrowserType[keyof typeof BrowserType];\n    }\n\n    interface ICPU extends IData<ICPU> {\n        architecture?: typeof CPUArch[keyof typeof CPUArch];\n    }\n\n    interface IDevice extends IData<IDevice> {\n        type?: typeof DeviceType[keyof typeof DeviceType];\n        vendor?: string;\n        model?: string;\n    }\n\n    interface IEngine extends IData<IEngine> {\n        name?: typeof EngineName[keyof typeof EngineName];\n        version?: string;\n    }\n\n    interface IOS extends IData<IOS> {\n        name?: string;\n        version?: string;\n    }\n\n    interface IResult extends IData<IResult> {\n        ua: string;\n        browser: IBrowser;\n        cpu: ICPU; \n        device: IDevice;\n        engine: IEngine; \n        os: IOS;\n    }\n\n    type RegexMap = ((RegExp | string | (string | RegExp | Function)[])[])[];\n    type UAParserProps = 'browser' | 'cpu' | 'device' | 'engine' | 'os';\n    type UAParserExt = Partial<Record<UAParserProps, RegexMap>> | Partial<Record<UAParserProps, RegexMap>>[];\n    export type UAParserHeaders = Record<string, string | string[] | undefined> | Headers;\n\n    export function UAParser(uastring?: string, extensions?: UAParserExt, headers?: UAParserHeaders): IResult;\n    export function UAParser(uastring?: string, headers?: UAParserHeaders): IResult;\n    export function UAParser(extensions?: UAParserExt, headers?: UAParserHeaders): IResult;\n    export function UAParser(headers?: UAParserHeaders): IResult;\n\n    export class UAParser {\n        \n        static readonly BROWSER: {\n            NAME: 'name'; \n            VERSION: 'version'; \n            MAJOR: 'major';\n            TYPE: 'type';\n        };\n        static readonly CPU: { \n            ARCHITECTURE: 'architecture'; \n        };\n        static readonly DEVICE: { \n            TYPE: 'type';\n            VENDOR: 'vendor'; \n            MODEL: 'model';\n            CONSOLE: 'console';\n            MOBILE: 'mobile';\n            SMARTTV: 'smarttv';\n            TABLET: 'tablet';\n            WEARABLE: 'wearable';\n            XR: 'xr';\n            EMBEDDED: 'embedded';\n        };\n        static readonly ENGINE: { \n            NAME: 'name'; \n            VERSION: 'version'; \n        };\n        static readonly OS: { \n            NAME: 'name';\n            VERSION: 'version'; \n        };\n        static readonly VERSION: string;\n\n        constructor(uastring?: string, extensions?: UAParserExt, headers?: Record<string, string>);\n        constructor(uastring?: string, headers?: Record<string, string>);\n        constructor(extensions?: UAParserExt, headers?: Record<string, string>);\n        constructor(headers?: Record<string, string>);\n    \n        getUA(): string;\n        getBrowser(): IBrowser;\n        getCPU(): ICPU;\n        getDevice(): IDevice;\n        getEngine(): IEngine;\n        getOS(): IOS;\n        getResult(): IResult;\n        setUA(uastring: string): UAParser;\n        useExtension(extensions: UAParserExt): UAParser;\n    }\n}\n\nexport as namespace UAParser;\nexport = UAParser;"
  },
  {
    "path": "src/main/ua-parser.js",
    "content": "/////////////////////////////////////////////////////////////////////////////////\n/* UAParser.js v2.0.9\n   Copyright © 2012-2026 Faisal Salman <f@faisalman.com>\n   AGPLv3 License *//*\n   Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.\n   Supports browser & node.js environment. \n   Demo   : https://uaparser.dev\n   Source : https://github.com/faisalman/ua-parser-js */\n/////////////////////////////////////////////////////////////////////////////////\n\n/* jshint esversion: 3 */ \n/* globals window */\n\n(function (window, undefined) {\n\n    'use strict';\n    \n    //////////////\n    // Constants\n    /////////////\n\n    var LIBVERSION  = '2.0.9',\n        UA_MAX_LENGTH = 500,\n        USER_AGENT  = 'user-agent',\n        EMPTY       = '',\n        UNKNOWN     = '?',\n        TYPEOF = {\n            FUNCTION    : 'function',\n            OBJECT      : 'object',\n            STRING      : 'string',\n            UNDEFINED   : 'undefined'\n        },\n\n        // properties\n        BROWSER     = 'browser',\n        CPU         = 'cpu',\n        DEVICE      = 'device',\n        ENGINE      = 'engine',\n        OS          = 'os',\n        RESULT      = 'result',\n\n        NAME        = 'name',\n        TYPE        = 'type',\n        VENDOR      = 'vendor',\n        VERSION     = 'version',\n        ARCHITECTURE= 'architecture',\n        MAJOR       = 'major',\n        MODEL       = 'model',\n\n        // device types\n        CONSOLE     = 'console',\n        MOBILE      = 'mobile',\n        TABLET      = 'tablet',\n        SMARTTV     = 'smarttv',\n        WEARABLE    = 'wearable',\n        XR          = 'xr',\n        EMBEDDED    = 'embedded',\n\n        // browser types\n        FETCHER     = 'fetcher',\n        INAPP       = 'inapp',\n\n        // client hints\n        BRANDS      = 'brands',\n        FORMFACTORS = 'formFactors',\n        FULLVERLIST = 'fullVersionList',\n        PLATFORM    = 'platform',\n        PLATFORMVER = 'platformVersion',\n        BITNESS     = 'bitness',\n        CH          = 'sec-ch-ua',\n        CH_FULL_VER_LIST= CH + '-full-version-list',\n        CH_ARCH         = CH + '-arch',\n        CH_BITNESS      = CH + '-' + BITNESS,\n        CH_FORM_FACTORS = CH + '-form-factors',\n        CH_MOBILE       = CH + '-' + MOBILE,\n        CH_MODEL        = CH + '-' + MODEL,\n        CH_PLATFORM     = CH + '-' + PLATFORM,\n        CH_PLATFORM_VER = CH_PLATFORM + '-version',\n        CH_ALL_VALUES   = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],\n\n        // device vendors\n        AMAZON      = 'Amazon',\n        APPLE       = 'Apple',\n        ASUS        = 'ASUS',\n        BLACKBERRY  = 'BlackBerry',\n        GOOGLE      = 'Google',\n        HUAWEI      = 'Huawei',\n        LENOVO      = 'Lenovo',\n        HONOR       = 'Honor',\n        LG          = 'LG',\n        MICROSOFT   = 'Microsoft',\n        MOTOROLA    = 'Motorola',\n        NVIDIA      = 'Nvidia',\n        ONEPLUS     = 'OnePlus',\n        OPPO        = 'OPPO',\n        SAMSUNG     = 'Samsung',\n        SHARP       = 'Sharp',\n        SONY        = 'Sony',\n        XIAOMI      = 'Xiaomi',\n        ZEBRA       = 'Zebra',\n\n        // browsers\n        CHROME      = 'Chrome',\n        CHROMIUM    = 'Chromium',\n        CHROMECAST  = 'Chromecast',\n        EDGE        = 'Edge',\n        FIREFOX     = 'Firefox',\n        OPERA       = 'Opera',\n        FACEBOOK    = 'Facebook',\n        SOGOU       = 'Sogou',\n\n        PREFIX_MOBILE  = 'Mobile ',\n        SUFFIX_BROWSER = ' Browser',\n\n        // os\n        WINDOWS     = 'Windows';\n   \n    var isWindow            = typeof window !== TYPEOF.UNDEFINED,\n        NAVIGATOR           = (isWindow && window.navigator) ? \n                                window.navigator : \n                                undefined,\n        NAVIGATOR_UADATA    = (NAVIGATOR && NAVIGATOR.userAgentData) ? \n                                NAVIGATOR.userAgentData : \n                                undefined;\n\n    ///////////\n    // Helper\n    //////////\n\n    var extend = function (defaultRgx, extensions) {\n            var mergedRgx = {};\n            var extraRgx = extensions;\n            if (!isExtensions(extensions)) {\n                extraRgx = {};\n                for (var i in extensions) {\n                    for (var j in extensions[i]) {\n                        extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);\n                    }\n                }\n            }\n            for (var k in defaultRgx) {\n                mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];\n            }\n            return mergedRgx;\n        },\n        enumerize = function (arr) {\n            var enums = {};\n            for (var i=0; i<arr.length; i++) {\n                enums[arr[i].toUpperCase()] = arr[i];\n            }\n            return enums;\n        },\n        has = function (str1, str2) {\n            if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {\n                for (var i in str1) {\n                    if (lowerize(str2) == lowerize(str1[i])) return true;\n                }\n                return false;\n            }\n            return isString(str1) ? lowerize(str2) == lowerize(str1) : false;\n        },\n        isExtensions = function (obj, deep) {\n            for (var prop in obj) {\n                return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);\n            }\n        },\n        isString = function (val) {\n            return typeof val === TYPEOF.STRING;\n        },\n        itemListToArray = function (header) {\n            if (!header) return undefined;\n            var arr = [];\n            var tokens = strip(/\\\\?\\\"/g, header).split(',');\n            for (var i = 0; i < tokens.length; i++) {\n                if (tokens[i].indexOf(';') > -1) {\n                    var token = trim(tokens[i]).split(';v=');\n                    arr[i] = { brand : token[0], version : token[1] };\n                } else {\n                    arr[i] = trim(tokens[i]);\n                }\n            }\n            return arr;\n        },\n        lowerize = function (str) {\n            return isString(str) ? str.toLowerCase() : str;\n        },\n        majorize = function (version) {\n            return isString(version) ? strip(/[^\\d\\.]/g, version).split('.')[0] : undefined;\n        },\n        setProps = function (arr) {\n            for (var i in arr) {\n                if (!arr.hasOwnProperty(i)) continue;\n\n                var propName = arr[i];\n                if (typeof propName == TYPEOF.OBJECT && propName.length == 2) {\n                    this[propName[0]] = propName[1];\n                } else {\n                    this[propName] = undefined;\n                }\n            }\n            return this;\n        },\n        strip = function (pattern, str) {\n            return isString(str) ? str.replace(pattern, EMPTY) : str;\n        },\n        stripQuotes = function (str) {\n            return strip(/\\\\?\\\"/g, str); \n        },\n        trim = function (str, len) {\n            str = strip(/^\\s\\s*/, String(str));\n            return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);\n    };\n\n    ///////////////\n    // Map helper\n    //////////////\n\n    var rgxMapper = function (ua, arrays) {\n\n            if(!ua || !arrays) return;\n\n            var i = 0, j, k, p, q, matches, match;\n\n            // loop through all regexes maps\n            while (i < arrays.length && !matches) {\n\n                var regex = arrays[i],       // even sequence (0,2,4,..)\n                    props = arrays[i + 1];   // odd sequence (1,3,5,..)\n                j = k = 0;\n\n                // try matching uastring with regexes\n                while (j < regex.length && !matches) {\n\n                    if (!regex[j]) { break; }\n                    matches = regex[j++].exec(ua);\n\n                    if (!!matches) {\n                        for (p = 0; p < props.length; p++) {\n                            match = matches[++k];\n                            q = props[p];\n                            // check if given property is actually array\n                            if (typeof q === TYPEOF.OBJECT && q.length > 0) {\n                                if (q.length === 2) {\n                                    if (typeof q[1] == TYPEOF.FUNCTION) {\n                                        // assign modified match\n                                        this[q[0]] = q[1].call(this, match);\n                                    } else {\n                                        // assign given value, ignore regex match\n                                        this[q[0]] = q[1];\n                                    }\n                                } else if (q.length >= 3) {\n                                    // Check whether q[1] FUNCTION or REGEX\n                                    if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) {\n                                        if (q.length > 3) {\n                                            this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;\n                                        } else {\n                                            // call function (usually string mapper)\n                                            this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n                                        }\n                                    } else {\n                                        if (q.length == 3) {\n                                            // sanitize match using given regex\n                                            this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n                                        } else if (q.length == 4) {\n                                            this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n                                        } else if (q.length > 4) {\n                                            this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined;\n                                        }\n                                    }\n                                }\n                            } else {\n                                this[q] = match ? match : undefined;\n                            }\n                        }\n                    }\n                }\n                i += 2;\n            }\n        },\n\n        strTest = function (str, map) {\n            return map.test.test(str) ? map.ifTrue : map.ifFalse;\n        },\n\n        strMapper = function (str, map) {\n\n            for (var i in map) {\n                // check if current value is array\n                if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {\n                    for (var j = 0; j < map[i].length; j++) {\n                        if (has(map[i][j], str)) {\n                            return (i === UNKNOWN) ? undefined : i;\n                        }\n                    }\n                } else if (has(map[i], str)) {\n                    return (i === UNKNOWN) ? undefined : i;\n                }\n            }\n            return map.hasOwnProperty('*') ? map['*'] : str;\n    };\n\n    ///////////////\n    // String map\n    //////////////\n\n    var windowsVersionMap = {\n            'ME'    : '4.90',\n            'NT 3.51': '3.51',\n            'NT 4.0': '4.0',\n            '2000'  : ['5.0', '5.01'],\n            'XP'    : ['5.1', '5.2'],\n            'Vista' : '6.0',\n            '7'     : '6.1',\n            '8'     : '6.2',\n            '8.1'   : '6.3',\n            '10'    : ['6.4', '10.0'],\n            'NT'    : ''\n        },\n        \n        formFactorsMap = {\n            'embedded'  : 'Automotive',\n            'mobile'    : 'Mobile',\n            'tablet'    : ['Tablet', 'EInk'],\n            'smarttv'   : 'TV',\n            'wearable'  : 'Watch',\n            'xr'        : ['VR', 'XR'],\n            '?'         : ['Desktop', 'Unknown'],\n            '*'         : undefined\n        },\n\n        browserHintsMap = {\n            'Chrome'        : 'Google Chrome',\n            'Edge'          : 'Microsoft Edge',\n            'Edge WebView2' : 'Microsoft Edge WebView2',\n            'Chrome WebView': 'Android WebView',\n            'Chrome Headless':'HeadlessChrome',\n            'Huawei Browser': 'HuaweiBrowser',\n            'MIUI Browser'  : 'Miui Browser',\n            'Opera Mobi'    : 'OperaMobile',\n            'Yandex'        : 'YaBrowser'\n    };\n\n    //////////////\n    // Regex map\n    /////////////\n\n    var defaultRegexes = {\n\n        browser : [[\n\n            // Most common regardless engine\n            /\\b(?:crmo|crios)\\/([\\w\\.]+)/i                                      // Chrome for Android/iOS\n            ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [\n            /webview.+edge\\/([\\w\\.]+)/i                                         // Microsoft Edge\n            ], [VERSION, [NAME, EDGE+' WebView'], [TYPE, INAPP]], [\n            /edg(?:e|ios|a)?\\/([\\w\\.]+)/i                                       \n            ], [VERSION, [NAME, 'Edge']], [\n\n            // Presto based\n            /(opera mini)\\/([-\\w\\.]+)/i,                                        // Opera Mini\n            /(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i,                 // Opera Mobi/Tablet\n            /(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i                           // Opera\n            ], [NAME, VERSION], [\n            /opios[\\/ ]+([\\w\\.]+)/i                                             // Opera mini on iphone >= 8.0\n            ], [VERSION, [NAME, OPERA+' Mini']], [\n            /\\bop(?:rg)?x\\/([\\w\\.]+)/i                                          // Opera GX\n            ], [VERSION, [NAME, OPERA+' GX']], [\n            /\\bopr\\/([\\w\\.]+)/i                                                 // Opera Webkit\n            ], [VERSION, [NAME, OPERA]], [\n\n            // Mixed\n            /\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i            // Baidu\n            ], [VERSION, [NAME, 'Baidu']], [\n            /\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i                       // Maxthon\n            ], [VERSION, [NAME, 'Maxthon']], [\n            /(kindle)\\/([\\w\\.]+)/i,                                             // Kindle\n            /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i,      \n                                                                                // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir\n            // Trident based\n            /(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i,        // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet\n            /(?:ms|\\()(ie) ([\\w\\.]+)/i,                                         // Internet Explorer\n\n            // Blink/Webkit/KHTML based                                         // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon/HiBrowser\n            /(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\\/v?([-\\w\\.]+)/i,\n                                                                                // Atlas/Rekonq/Puffin/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon\n            /(brave)(?: chrome)?\\/([\\d\\.]+)/i,                                  // Brave\n            /(aloha|heytap|ovi|115|surf|qwant)browser\\/([\\d\\.]+)/i,             // Aloha/HeyTap/Ovi/115/Surf\n            /(qwant)(?:ios|mobile)\\/([\\d\\.]+)/i,                                // Qwant\n            /(ecosia|weibo)(?:__| \\w+@)([\\d\\.]+)/i                              // Ecosia/Weibo\n            ], [NAME, VERSION], [\n            /quark(?:pc)?\\/([-\\w\\.]+)/i                                         // Quark\n            ], [VERSION, [NAME, 'Quark']], [\n            /\\bddg\\/([\\w\\.]+)/i                                                 // DuckDuckGo\n            ], [VERSION, [NAME, 'DuckDuckGo']], [\n            /(?:\\buc? ?browser|(?:juc.+)ucweb| ucpc)[\\/ ]?([\\w\\.]+)/i           // UCBrowser\n            ], [VERSION, [NAME, 'UCBrowser']], [\n            /microm.+\\bqbcore\\/([\\w\\.]+)/i,                                     // WeChat Desktop for Windows Built-in Browser\n            /\\bqbcore\\/([\\w\\.]+).+microm/i,\n            /micromessenger\\/([\\w\\.]+)/i                                        // WeChat\n            ], [VERSION, [NAME, 'WeChat']], [\n            /konqueror\\/([\\w\\.]+)/i                                             // Konqueror\n            ], [VERSION, [NAME, 'Konqueror']], [\n            /trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i                       // IE11\n            ], [VERSION, [NAME, 'IE']], [\n            /ya(?:search)?browser\\/([\\w\\.]+)/i                                  // Yandex\n            ], [VERSION, [NAME, 'Yandex']], [\n            /slbrowser\\/([\\w\\.]+)/i                                             // Smart Lenovo Browser\n            ], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [\n            /(av(?:ast|g|ira))\\/([\\w\\.]+)/i                                     // Avast/AVG/Avira Secure Browser\n            ], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [\n            /norton\\/([\\w\\.]+)/i                                                // Norton Private Browser\n            ], [VERSION, [NAME, 'Norton Private' + SUFFIX_BROWSER]], [\n            /\\bfocus\\/([\\w\\.]+)/i                                               // Firefox Focus\n            ], [VERSION, [NAME, FIREFOX+' Focus']], [\n            / mms\\/([\\w\\.]+)$/i                                                 // Opera Neon\n            ], [VERSION, [NAME, OPERA+' Neon']], [\n            / opt\\/([\\w\\.]+)$/i                                                 // Opera Touch\n            ], [VERSION, [NAME, OPERA+' Touch']], [\n            /coc_coc\\w+\\/([\\w\\.]+)/i                                            // Coc Coc Browser\n            ], [VERSION, [NAME, 'Coc Coc']], [\n            /dolfin\\/([\\w\\.]+)/i                                                // Dolphin\n            ], [VERSION, [NAME, 'Dolphin']], [\n            /coast\\/([\\w\\.]+)/i                                                 // Opera Coast\n            ], [VERSION, [NAME, OPERA+' Coast']], [\n            /miuibrowser\\/([\\w\\.]+)/i                                           // MIUI Browser\n            ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [\n            /fxios\\/([\\w\\.-]+)/i                                                // Firefox for iOS\n            ], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [\n            /\\bqihoobrowser\\/?([\\w\\.]*)/i                                       // 360\n            ], [VERSION, [NAME, '360']], [\n            /\\b(qq)\\/([\\w\\.]+)/i                                                // QQ\n            ], [[NAME, /(.+)/, '$1Browser'], VERSION], [\n            /(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i\n            ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [              // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser\n            /samsungbrowser\\/([\\w\\.]+)/i                                        // Samsung Internet\n            ], [VERSION, [NAME, SAMSUNG + ' Internet']], [\n            /metasr[\\/ ]?([\\d\\.]+)/i                                            // Sogou Explorer\n            ], [VERSION, [NAME, SOGOU + ' Explorer']], [\n            /(sogou)mo\\w+\\/([\\d\\.]+)/i                                          // Sogou Mobile\n            ], [[NAME, SOGOU + ' Mobile'], VERSION], [\n            /(electron)\\/([\\w\\.]+) safari/i,                                    // Electron-based App\n            /(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i,                   // Tesla\n            /m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i   // QQ/2345\n            ], [NAME, VERSION], [\n            /(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i            // LieBao Browser/Luakit/Rekonq/Steam\n            ], [NAME], [\n            /ome\\/([\\w\\.]+).+(iron(?= saf)|360(?=[es]e$))/i                     // Iron / 360\n            ], [VERSION, NAME], [\n\n            // WebView\n            /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i       // Facebook App for iOS & Android\n            ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [\n            /(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i,                             // Kakao App\n            /(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i,                                  // Naver InApp\n            /(daum)apps[\\/ ]([\\w\\.]+)/i,                                        // Daum App\n            /safari (line)\\/([\\w\\.]+)/i,                                        // Line App for iOS\n            /\\b(line)\\/([\\w\\.]+)\\/iab/i,                                        // Line App for Android\n            /(alipay)client\\/([\\w\\.]+)/i,                                       // Alipay\n            /(twitter)(?:and| f.+e\\/([\\w\\.]+))/i,                               // Twitter\n            /(bing)(?:web|sapphire)\\/([\\w\\.]+)/i,                               // Bing\n            /(instagram|snapchat|klarna)[\\/ ]([-\\w\\.]+)/i                       // Instagram/Snapchat/Klarna\n            ], [NAME, VERSION, [TYPE, INAPP]], [\n            /\\bgsa\\/([\\w\\.]+) .*safari\\//i                                      // Google Search Appliance on iOS\n            ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [\n            /(?:musical_ly|trill)(?:.+app_?version\\/|_)([\\w\\.]+)/i              // TikTok\n            ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [\n            /\\[(linkedin)app\\]/i                                                // LinkedIn App for iOS & Android\n            ], [NAME, [TYPE, INAPP]], [\n            /(zalo(?:app)?)[\\/\\sa-z]*([\\w\\.-]+)/i                               // Zalo \n            ], [[NAME, /(.+)/, 'Zalo'], VERSION, [TYPE, INAPP]], [\n\n            /(chromium)[\\/ ]([-\\w\\.]+)/i                                        // Chromium\n            ], [NAME, VERSION], [\n\n            /ome-(lighthouse)$/i                                                // Chrome Lighthouse\n            ], [NAME, [TYPE, FETCHER]], [\n\n            /headlesschrome(?:\\/([\\w\\.]+)| )/i                                  // Chrome Headless\n            ], [VERSION, [NAME, CHROME+' Headless']], [\n\n            /wv\\).+chrome\\/([\\w\\.]+).+edgw\\//i                                  // Edge WebView2\n            ], [VERSION, [NAME, EDGE+' WebView2'], [TYPE, INAPP]], [\n\n            /; wv\\).+(chrome)\\/([\\w\\.]+)/i                                      // Chrome WebView\n            ], [[NAME, CHROME+' WebView'], VERSION, [TYPE, INAPP]], [\n\n            /droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i           // Android Browser\n            ], [VERSION, [NAME, 'Android' + SUFFIX_BROWSER]], [\n\n            /chrome\\/([\\w\\.]+) mobile/i                                         // Chrome Mobile\n            ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [\n\n            /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i       // Chrome/OmniWeb/Arora/Tizen/Nokia\n            ], [NAME, VERSION], [\n\n            /version\\/([\\w\\.\\,]+) .*mobile(?:\\/\\w+ | ?)safari/i                 // Safari Mobile\n            ], [VERSION, [NAME, PREFIX_MOBILE + 'Safari']], [\n            /iphone .*mobile(?:\\/\\w+ | ?)safari/i\n            ], [[NAME, PREFIX_MOBILE + 'Safari']], [\n            /version\\/([\\w\\.\\,]+) .*(safari)/i                                  // Safari\n            ], [VERSION, NAME], [\n            /webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i                      // Safari < 3.0\n            ], [NAME, [VERSION, '1']], [\n\n            /(webkit|khtml)\\/([\\w\\.]+)/i\n            ], [NAME, VERSION], [\n\n            // Gecko based\n            /(?:mobile|tablet);.*(firefox)\\/([\\w\\.-]+)/i                        // Firefox Mobile\n            ], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [\n            /(navigator|netscape\\d?)\\/([-\\w\\.]+)/i                              // Netscape\n            ], [[NAME, 'Netscape'], VERSION], [\n            /(wolvic|librewolf)\\/([\\w\\.]+)/i                                    // Wolvic/LibreWolf\n            ], [NAME, VERSION], [\n            /mobile vr; rv:([\\w\\.]+)\\).+firefox/i                               // Firefox Reality\n            ], [VERSION, [NAME, FIREFOX+' Reality']], [\n            /ekiohf.+(flow)\\/([\\w\\.]+)/i,                                       // Flow\n            /(swiftfox)/i,                                                      // Swiftfox\n            /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,\n                                                                                // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n            /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\\/([-\\w\\.]+)$/i,\n                                                                                // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n            /(firefox)\\/([\\w\\.]+)/i,                                            // Other Firefox-based\n            /(mozilla)\\/([\\w\\.]+(?= .+rv\\:.+gecko\\/\\d+)|[0-4][\\w\\.]+(?!.+compatible))/i, // Mozilla\n\n            // Other\n            /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,\n                                                                                // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird\n            /\\b(links) \\(([\\w\\.]+)/i                                            // Links\n            ], [NAME, [VERSION, /_/g, '.']], [\n            \n            /(cobalt)\\/([\\w\\.]+)/i                                              // Cobalt\n            ], [NAME, [VERSION, /[^\\d\\.]+./, EMPTY]]\n        ],\n\n        cpu : [[\n\n            /\\b((amd|x|x86[-_]?|wow|win)64)\\b/i                                 // AMD64 (x64)\n            ], [[ARCHITECTURE, 'amd64']], [\n\n            /(ia32(?=;))/i,                                                     // IA32 (quicktime)\n            /\\b((i[346]|x)86)(pc)?\\b/i                                          // IA32 (x86)\n            ], [[ARCHITECTURE, 'ia32']], [\n\n            /\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i                               // ARM64\n            ], [[ARCHITECTURE, 'arm64']], [\n\n            /\\b(arm(v[67])?ht?n?[fl]p?)\\b/i                                     // ARMHF\n            ], [[ARCHITECTURE, 'armhf']], [\n\n            // PocketPC mistakenly identified as PowerPC\n            /( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i\n            ], [[ARCHITECTURE, 'arm']], [\n\n            / sun4\\w[;\\)]/i                                                     // SPARC\n            ], [[ARCHITECTURE, 'sparc']], [\n                                                                                // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n            /\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i,\n            /((ppc|powerpc)(64)?)( mac|;|\\))/i,                                 // PowerPC\n            /(?:osf1|[freopnt]{3,4}bsd) (alpha)/i                               // Alpha\n            ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [\n            /mc680.0/i\n            ], [[ARCHITECTURE, '68k']], [\n            /winnt.+\\[axp/i\n            ], [[ARCHITECTURE, 'alpha']]\n        ],\n\n        device : [[\n\n            //////////////////////////\n            // MOBILES & TABLETS\n            /////////////////////////\n\n            // Samsung\n            /\\b(sch-i[89]0\\d|shw-m380s|sm-[ptx]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus 10)/i\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [\n            /\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,\n            /samsung[- ]((?!sm-[lr]|browser)[-\\w]+)/i,\n            /sec-(sgh\\w+)/i\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [\n\n            // Apple\n            /(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)[\\/\\);]/i                           // iPod/iPhone\n            ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [\n            /\\b(?:ios|apple\\w+)\\/.+[\\(\\/](ipad)/i,                              // iPad\n            /\\b(ipad)[\\d,]*[;\\] ].+(mac |i(pad)?)os/i\n            ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [\n            /(macintosh);/i\n            ], [MODEL, [VENDOR, APPLE]], [\n\n            // Sharp\n            /\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i\n            ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [\n\n            // Honor\n            /\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i\n            ], [MODEL, [VENDOR, HONOR], [TYPE, TABLET]], [\n            /honor([-\\w ]+)[;\\)]/i\n            ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [\n\n            // Huawei\n            /\\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\\w\\. ]*(?= bui|\\)))\\b(?!.+d\\/s)/i\n            ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [\n            /(?:huawei) ?([-\\w ]+)[;\\)]/i,\n            /\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][\\dc][adnt]?)\\b(?!.+d\\/s)/i\n            ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [\n\n            // Xiaomi\n            /oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,\n            /\\b(?:xiao)?((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i               // Mi Pad tablets\n            ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [\n\n            /\\b; (\\w+) build\\/hm\\1/i,                                           // Xiaomi Hongmi 'numeric' models\n            /\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i,                             // Xiaomi Hongmi\n                                                                                // Xiaomi Redmi / POCO / Black Shark / Qin\n            /oid[^\\)]+; (redmi[\\-_ ]?(?:note|k)?[\\w_ ]+|m?[12]\\d[01]\\d\\w{3,6}|poco[\\w ]+|(shark )?\\w{3}-[ah]0|qin ?[1-3](s\\+|ultra| pro)?)( bui|; wv|\\))/i,\n                                                                                // Xiaomi Mi\n            /\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\\d{0,2}\\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\\))/i,\n            / ([\\w ]+) miui\\/v?\\d/i\n            ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [\n\n            // OnePlus\n            /droid.+; (cph2[3-6]\\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\\d|p[g-l]\\w[1m]10)\\b/i,\n            /(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i\n            ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [\n\n            // OPPO\n            /; (\\w+) bui.+ oppo/i,\n            /\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i\n            ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [\n            /\\b(opd2(\\d{3}a?))(?: bui|\\))/i\n            ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [\n\n            // BLU\n            /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\\w\\+ ]*)(?: bui|\\))/i  // Vivo series\n            ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [    \n\n            // Vivo\n            /; vivo (\\w+)(?: bui|\\))/i,\n            /\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i\n            ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n            // Realme\n            /\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i\n            ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n            // Lenovo\n            /(ideatab[-\\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\\d{3,4}(?:f[cu]|xu|[av])|yt\\d?-[jx]?\\d+[lfmx])( bui|;|\\)|\\/)/i,\n            /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i\n            ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [            \n            /lenovo[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i\n            ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [\n\n            // Motorola\n            /\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,\n            /\\bmot(?:orola)?[- ]([\\w\\s]+)(\\)| bui)/i,\n            /((?:moto(?! 360)[-\\w\\(\\) ]+|xt\\d{3,4}[cgkosw\\+]?[-\\d]*|nexus 6)(?= bui|\\)))/i\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [\n            /\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [\n\n            // LG\n            /\\b(?:lg)?([vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i\n            ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [\n            /(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,\n            /\\blg[-e;\\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\\w+)/i,\n            /\\blg-?([\\d\\w]+) bui/i\n            ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [\n\n            // Nokia\n            /(nokia) (t[12][01])/i\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n            /(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,\n            /nokia[-_ ]?(([-\\w\\. ]*?))( bui|\\)|;|\\/)/i\n            ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [\n\n            // Google\n            /(pixel (c|tablet))\\b/i                                             // Google Pixel C/Tablet\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [\n                                                                                // Google Pixel\n            /droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\\d ]*a?( pro)?( xl)?( fold)?( \\(5g\\))?)( bui|\\))/i\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [\n            /(google) (pixelbook( go)?)/i\n            ], [VENDOR, MODEL], [\n\n            // Sony\n            /droid.+; (a?\\d[0-2]{2}so|[c-g]\\d{4}|so[-gl]\\w+|xq-\\w\\w\\d\\d)(?= bui|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i\n            ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [\n            /sony tablet [ps]/i,\n            /\\b(?:sony)?sgp\\w+(?: bui|\\))/i\n            ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [\n\n            // Amazon\n            /(alexa)webm/i,\n            /(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i,                           // Kindle Fire without Silk / Echo Show\n            /(kf[a-z]+)( bui|\\)).+silk\\//i                                      // Kindle Fire HD\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [\n            /((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i                     // Fire Phone\n            ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [\n\n            // BlackBerry\n            /(playbook);[-\\w\\),; ]+(rim)/i                                      // BlackBerry PlayBook\n            ], [MODEL, VENDOR, [TYPE, TABLET]], [\n            /\\b((?:bb[a-f]|st[hv])100-\\d)/i,\n            /(?:blackberry|\\(bb10;) (\\w+)/i\n            ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [\n\n            // Asus\n            /(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i\n            ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [\n            / (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i\n            ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [\n\n            // HTC\n            /(nexus 9)/i                                                        // HTC Nexus 9\n            ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n            /(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i,                         // HTC\n\n            // ZTE\n            /(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,\n            /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i         // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n            ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n            // TCL\n            /tcl (xess p17aa)/i,\n            /droid [\\w\\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\\w(\\w|\\w\\w))?(\\)| bui)/i\n            ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [\n            /droid [\\w\\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\\w(\\w|\\w\\w))?(\\)| bui)/i\n            ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [\n\n            // itel\n            /(itel) ((\\w+))/i\n            ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [\n\n            // Acer\n            /droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i\n            ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n            // Meizu\n            /droid.+; (m[1-5] note) bui/i,\n            /\\bmz-([-\\w]{2,})/i\n            ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n                \n            // Ulefone\n            /; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [\n\n            // Energizer\n            /; (energy ?\\w+)(?: bui|\\))/i,\n            /; energizer ([\\w ]+)(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [\n\n            // Cat\n            /; cat (b35);/i,\n            /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [\n\n            // Smartfren\n            /((?:new )?andromax[\\w- ]+)(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [\n\n            // Nothing\n            /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i\n            ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [\n\n            // Archos\n            /; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,\n            /archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i\n            ], [MODEL, [VENDOR, 'Archos'], [TYPE, TABLET]], [\n            /archos ([\\w ]+)( b|\\))/i,\n            /; (ac[3-6]\\d\\w{2,8})( b|\\))/i \n            ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [\n\n            // Blackview\n            /blackview ([-\\w ]+)( b|\\))/i,\n            /; (bv\\d{4}[-\\w ]*)( b|\\))/i\n            ], [MODEL, [VENDOR, 'Blackview'], [TYPE, MOBILE]], [\n\n            // HMD\n            /; (n159v)/i\n            ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [\n\n            // T-Mobile\n            /((revvl[ \\w\\+]+|tm(?:rv|af)\\w*[45]g(?:tb)?))( b|\\))/i\n            ], [MODEL, [TYPE, strTest, { 'test': /ta?b/i, 'ifTrue': TABLET, 'ifFalse': MOBILE }], [VENDOR, 'T-Mobile']], [\n\n            // MIXED\n            /(imo) (tab \\w+)/i,                                                 // IMO\n            /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i                     // Infinix XPad / Tecno\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n            /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,\n                                                                                // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan\n                                                                                // BLU/Coolpad/CUBOT/HMD/IMO/Infinix/Lava/OnePlus/TCL/Wiko\n            /; (blu|coolpad|cubot|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([-\\w\\+ ]+?)(?: bui|\\)|; r)/i,\n            /(hp) ([\\w ]+\\w)/i,                                                 // HP iPAQ\n            /(microsoft); (lumia[\\w ]+)/i,                                      // Microsoft Lumia\n            /(oppo) ?([\\w ]+) bui/i,                                            // OPPO\n            /(hisense) ([ehv][\\w ]+)\\)/i,                                       // Hisense\n            /droid[^;]+; (philips)[_ ]([sv-x][\\d]{3,4}[xz]?)/i                  // Philips\n            ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n            /(kobo)\\s(ereader|touch)/i,                                         // Kobo\n            /(hp).+(touchpad(?!.+tablet)|tablet)/i,                             // HP TouchPad\n            /(kindle)\\/([\\w\\.]+)/i                                              // Kindle\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n            /(surface duo)/i                                                    // Surface Duo\n            ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [\n            /droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i                                 // Fairphone\n            ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n            /((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i              // Nvidia Tablets\n            ], [MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]], [\n            /(sprint) (\\w+)/i                                                   // Sprint Phones\n            ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n            /(kin\\.[onetw]{3})/i                                                // Microsoft Kin\n            ], [[MODEL, /\\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [\n            /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i               // Zebra\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [\n            /droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [\n\n            ///////////////////\n            // SMARTTVS\n            ///////////////////\n\n            /(philips)[\\w ]+tv/i,                                               // Philips\n            /smart-tv.+(samsung)/i                                              // Samsung\n            ], [VENDOR, [TYPE, SMARTTV]], [\n            /hbbtv.+maple;(\\d+)/i\n            ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [\n            /(vizio)(?: |.+model\\/)(\\w+-\\w+)/i,                                 // Vizio\n            /tcast.+(lg)e?. ([-\\w]+)/i                                          // LG SmartTV\n            ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n            /(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i\n            ], [[VENDOR, LG], [TYPE, SMARTTV]], [\n            /(apple) ?tv/i                                                      // Apple TV\n            ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [\n            /crkey.*devicetype\\/chromecast/i                                    // Google Chromecast Third Generation\n            ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /crkey.*devicetype\\/([^/]*)/i                                       // Google Chromecast with specific device type\n            ], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /fuchsia.*crkey/i                                                   // Google Chromecast Nest Hub\n            ], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /crkey/i                                                            // Google Chromecast, Linux-based or unknown\n            ], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /(portaltv)/i                                                       // Facebook Portal TV\n            ], [MODEL, [VENDOR, FACEBOOK], [TYPE, SMARTTV]], [\n            /droid.+aft(\\w+)( bui|\\))/i                                         // Fire TV\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [\n            /(shield \\w+ tv)/i                                                  // Nvidia Shield TV\n            ], [MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]], [\n            /\\(dtv[\\);].+(aquos)/i,\n            /(aquos-tv[\\w ]+)\\)/i                                               // Sharp\n            ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[\n            /(bravia[\\w ]+)( bui|\\))/i                                          // Sony\n            ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [\n            /(mi(tv|box)-?\\w+) bui/i                                            // Xiaomi\n            ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [\n            /Hbbtv.*(technisat) (.*);/i                                         // TechniSAT\n            ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n            /\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i,                          // Roku\n            /hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i         // HbbTV devices\n            ], [[VENDOR, /.+\\/(\\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [\n\n            ///////////////////\n            // CONSOLES\n            ///////////////////\n\n            /(playstation \\w+)/i                                                // Playstation\n            ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [\n            /\\b(xbox(?: one)?(?!; xbox))[\\); ]/i                                // Microsoft Xbox\n            ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [\n            /(ouya)/i,                                                          // Ouya\n            /(nintendo) (\\w+)/i,                                                // Nintendo\n            /(retroid) (pocket ([^\\)]+))/i,                                     // Retroid Pocket\n            /(valve).+(steam deck)/i,\n            /droid.+; ((shield|rgcube|gr0006))( bui|\\))/i                       // Nvidia Portable/Anbernic/Logitech\n            ], [[VENDOR, strMapper, { 'Nvidia': 'Shield', 'Anbernic': 'RGCUBE', 'Logitech': 'GR0006' }], MODEL, [TYPE, CONSOLE]], [\n\n            ///////////////////\n            // WEARABLES\n            ///////////////////\n\n            /\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i                       // Samsung Galaxy Watch\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [\n            /((pebble))app/i,                                                   // Pebble\n            /(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i // Asus ZenWatch / LG Watch / Pixel Watch / Xiaomi Watch\n            ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n            /(ow(?:19|20)?we?[1-3]{1,3})/i                                      // Oppo Watch\n            ], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [\n            /(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i                              // Apple Watch\n            ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [\n            /(opwwe\\d{3})/i                                                     // OnePlus Watch\n            ], [MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]], [\n            /(moto 360)/i                                                       // Motorola 360\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]], [\n            /(smartwatch 3)/i                                                   // Sony SmartWatch\n            ], [MODEL, [VENDOR, SONY], [TYPE, WEARABLE]], [\n            /(g watch r)/i                                                      // LG G Watch R\n            ], [MODEL, [VENDOR, LG], [TYPE, WEARABLE]], [\n            /droid.+; (wt63?0{2,3})\\)/i\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [\n\n            ///////////////////\n            // XR\n            ///////////////////\n\n            /droid.+; (glass) \\d/i                                              // Google Glass\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [\n            /(pico) ([\\w ]+) os\\d/i                                             // Pico\n            ], [VENDOR, MODEL, [TYPE, XR]], [\n            /(quest( \\d| pro)?s?).+vr/i                                         // Meta Quest\n            ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [\n            /mobile vr; rv.+firefox/i                                           // Unidentifiable VR device using Firefox Reality / Wolvic\n            ], [[TYPE, XR]], [\n\n            ///////////////////\n            // EMBEDDED\n            ///////////////////\n\n            /(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i                              // Tesla\n            ], [VENDOR, [TYPE, EMBEDDED]], [\n            /(aeobc)\\b/i                                                        // Echo Dot\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [\n            /(homepod).+mac os/i                                                // Apple HomePod\n            ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [\n            /windows iot/i                                                      // Unidentifiable embedded device using Windows IoT\n            ], [[TYPE, EMBEDDED]], [\n\n            ////////////////////\n            // MIXED (GENERIC)\n            ///////////////////\n\n            /droid.+; ([\\w- ]+) (4k|android|smart|google)[- ]?tv/i              // Unidentifiable SmartTV\n            ], [MODEL, [TYPE, SMARTTV]], [\n            /\\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\\w ]+safari)\\b/i\n            ], [[TYPE, SMARTTV]], [\n            /droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew|; hmsc).+?(mobile|vr|\\d) safari/i\n            ], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [\n            /\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i                      // Unidentifiable Tablet\n            ], [[TYPE, TABLET]], [\n            /(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i    // Unidentifiable Mobile\n            ], [[TYPE, MOBILE]], [\n            /droid .+?; ([\\w\\. -]+)( bui|\\))/i                                  // Generic Android Device\n            ], [MODEL, [VENDOR, 'Generic']]\n        ],\n\n        engine : [[\n\n            /windows.+ edge\\/([\\w\\.]+)/i                                       // EdgeHTML\n            ], [VERSION, [NAME, EDGE+'HTML']], [\n\n            /(arkweb)\\/([\\w\\.]+)/i                                              // ArkWeb\n            ], [NAME, VERSION], [\n\n            /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i                         // Blink\n            ], [VERSION, [NAME, 'Blink']], [\n\n            /(presto)\\/([\\w\\.]+)/i,                                             // Presto\n            /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo\n            /ekioh(flow)\\/([\\w\\.]+)/i,                                          // Flow\n            /(khtml|tasman|links|dillo)[\\/ ]\\(?([\\w\\.]+)/i,                     // KHTML/Tasman/Links/Dillo\n            /(icab)[\\/ ]([23]\\.[\\d\\.]+)/i,                                      // iCab\n\n            /\\b(libweb)/i                                                       // LibWeb\n            ], [NAME, VERSION], [\n            /ladybird\\//i\n            ], [[NAME, 'LibWeb']], [\n\n            /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i                                     // Gecko\n            ], [VERSION, NAME]\n        ],\n\n        os : [[\n\n            // Windows\n            /(windows nt) (6\\.[23]); arm/i                                      // Windows RT\n            ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [\n            /(windows (?:phone|mobile|iot))(?: os)?[\\/ ]?([\\d\\.]*( se)?)/i,     // Windows IoT/Mobile/Phone\n                                                                                // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11\n            /(windows)[\\/ ](1[01]|2000|3\\.1|7|8(\\.1)?|9[58]|me|server 20\\d\\d( r2)?|vista|xp)/i\n            ], [NAME, VERSION], [\n            /windows nt ?([\\d\\.\\)]*)(?!.+xbox)/i,\n            /\\bwin(?=3| ?9|n)(?:nt| 9x )?([\\d\\.;]*)/i\n            ], [[VERSION, /(;|\\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [\n            /(windows ce)\\/?([\\d\\.]*)/i                                         // Windows CE\n            ], [NAME, VERSION], [\n\n            // iOS/macOS\n            /[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i,             // iOS\n            /(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\\/ ]([\\w\\.]+)/i,\n            /\\btvos ?([\\w\\.]+)/i,\n            /cfnetwork\\/.+darwin/i\n            ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n            /(mac os x) ?([\\w\\. ]*)/i,\n            /(macintosh|mac_powerpc\\b)(?!.+(haiku|morphos))/i                   // Mac OS\n            ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [\n\n            // Google Chromecast\n            /android ([\\d\\.]+).*crkey/i                                         // Google Chromecast, Android-based\n            ], [VERSION, [NAME, CHROMECAST + ' Android']], [\n            /fuchsia.*crkey\\/([\\d\\.]+)/i                                        // Google Chromecast, Fuchsia-based\n            ], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [\n            /crkey\\/([\\d\\.]+).*devicetype\\/smartspeaker/i                       // Google Chromecast, Linux-based Smart Speaker\n            ], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [\n            /linux.*crkey\\/([\\d\\.]+)/i                                          // Google Chromecast, Legacy Linux-based\n            ], [VERSION, [NAME, CHROMECAST + ' Linux']], [\n            /crkey\\/([\\d\\.]+)/i                                                 // Google Chromecast, unknown\n            ], [VERSION, [NAME, CHROMECAST]], [\n\n            // Mobile OSes\n            /droid ([\\w\\.]+)\\b.+(android[- ]x86)/i                              // Android-x86\n            ], [VERSION, NAME], [                                               \n            /(ubuntu) ([\\w\\.]+) like android/i                                  // Ubuntu Touch\n            ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [\n            /(harmonyos)[\\/ ]?([\\d\\.]*)/i,                                      // HarmonyOS\n                                                                                // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen\n            /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\\w*[-\\/\\.; ]?([\\d\\.]*)/i\n            ], [NAME, VERSION], [\n            /\\(bb(10);/i                                                        // BlackBerry 10\n            ], [VERSION, [NAME, BLACKBERRY]], [\n            /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i       // Symbian\n            ], [VERSION, [NAME, 'Symbian']], [\n            /mozilla\\/[\\d\\.]+ \\((?:mobile[;\\w ]*|tablet|tv|[^\\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\\w\\.]+)\\).+gecko\\//i // Firefox OS\n            ], [VERSION, [NAME, FIREFOX+' OS']], [\n            /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i,                             // WebOS\n            /webos(?:[ \\/]?|\\.tv-20(?=2[2-9]))(\\d[\\d\\.]*)/i\n            ], [VERSION, [NAME, 'webOS']], [\n            /web0s;.+?(?:chr[o0]me|safari)\\/(\\d+)/i\n                                                                                // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine\n            ], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [                   \n            /watch(?: ?os[,\\/ ]|\\d,\\d\\/)([\\d\\.]+)/i                              // watchOS\n            ], [VERSION, [NAME, 'watchOS']], [\n\n            // Google ChromeOS\n            /cros [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i                                    // Chromium OS\n            ], [VERSION, [NAME, 'Chrome OS']],[\n\n            // Smart TVs\n            /kepler ([\\w\\.]+); (aft|aeo)/i                                      // Vega OS\n            ], [VERSION, [NAME, 'Vega OS']],[\n            /(netrange)mmh/i,                                                   // Netrange\n            /(nettv)\\/(\\d+\\.[\\w\\.]+)/i,                                         // NetTV\n\n            // Console\n            /(nintendo|playstation) (\\w+)/i,                                    // Nintendo/Playstation\n            /(xbox); +xbox ([^\\);]+)/i,                                         // Microsoft Xbox (360, One, X, S, Series X, Series S)\n            /(pico) .+os([\\w\\.]+)/i,                                            // Pico\n\n            // Other\n            /\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i,                            // Joli/Palm\n            /linux.+(mint)[\\/\\(\\) ]?([\\w\\.]*)/i,                                // Mint\n            /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\\d\\.]*)/i,  // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch\n            /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\\/ ]?(?!chrom|package)([-\\w\\.]*)/i,\n                                                                                // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix\n            /((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i,                              // Solaris\n            /\\b(aix)[; ]([1-9\\.]{0,4})/i,                                       // AIX\n            /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\\w*| ?)([\\w\\.]*)/i,         // Hurd/Linux/MorphOS\n            /(gnu) ?([\\w\\.]*)/i,                                                // GNU\n            /\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly\n            /(haiku) ?(r\\d)?/i                                                  // Haiku\n            ], [NAME, VERSION], [\n            /(sunos) ?([\\d\\.]*)/i                                               // Solaris\n            ], [[NAME, 'Solaris'], VERSION], [\n            /\\b(beos|os\\/2|amigaos|openvms|hp-ux|serenityos)/i,                 // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS\n            /(unix) ?([\\w\\.]*)/i                                                // UNIX\n            ], [NAME, VERSION]\n        ]\n    };\n\n    /////////////////\n    // Factories\n    ////////////////\n\n    var defaultProps = (function () {\n            var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};\n            setProps.call(props.init, [\n                [BROWSER, [NAME, VERSION, MAJOR, TYPE]],\n                [CPU, [ARCHITECTURE]],\n                [DEVICE, [TYPE, MODEL, VENDOR]],\n                [ENGINE, [NAME, VERSION]],\n                [OS, [NAME, VERSION]]\n            ]);\n            setProps.call(props.isIgnore, [\n                [BROWSER, [VERSION, MAJOR]],\n                [ENGINE, [VERSION]],\n                [OS, [VERSION]]\n            ]);\n            setProps.call(props.isIgnoreRgx, [\n                [BROWSER, / ?browser$/i],\n                [OS, / ?os$/i]\n            ]);\n            setProps.call(props.toString, [\n                [BROWSER, [NAME, VERSION]],\n                [CPU, [ARCHITECTURE]],\n                [DEVICE, [VENDOR, MODEL]],\n                [ENGINE, [NAME, VERSION]],\n                [OS, [NAME, VERSION]]\n            ]);\n            return props;\n    })();\n\n    var createIData = function (item, itemType) {\n\n        var init_props = defaultProps.init[itemType],\n            is_ignoreProps = defaultProps.isIgnore[itemType] || 0,\n            is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,\n            toString_props = defaultProps.toString[itemType] || 0;\n\n        function IData () {\n            setProps.call(this, init_props);\n        }\n\n        IData.prototype.getItem = function () {\n            return item;\n        };\n\n        IData.prototype.withClientHints = function () {\n\n            // nodejs / non-client-hints browsers\n            if (!NAVIGATOR_UADATA) {\n                return item\n                        .parseCH()\n                        .get();\n            }\n\n            // browsers based on chromium 85+\n            return NAVIGATOR_UADATA\n                    .getHighEntropyValues(CH_ALL_VALUES)\n                    .then(function (res) {\n                        return item\n                                .setCH(new UACHData(res, false))\n                                .parseCH()\n                                .get();\n            });\n        };\n\n        IData.prototype.withFeatureCheck = function () {\n            return item.detectFeature().get();\n        };\n\n        if (itemType != RESULT) {\n            IData.prototype.is = function (strToCheck) {\n                var is = false;\n                for (var i in this) {\n                    if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {\n                        is = true;\n                        if (strToCheck != TYPEOF.UNDEFINED) break;\n                    } else if (strToCheck == TYPEOF.UNDEFINED && is) {\n                        is = !is;\n                        break;\n                    }\n                }\n                return is;\n            };\n            IData.prototype.toString = function () {\n                var str = EMPTY;\n                for (var i in toString_props) {\n                    if (typeof(this[toString_props[i]]) !== TYPEOF.UNDEFINED) {\n                        str += (str ? ' ' : EMPTY) + this[toString_props[i]];\n                    }\n                }\n                return str || TYPEOF.UNDEFINED;\n            };\n        }\n\n        IData.prototype.then = function (cb) { \n            var that = this;\n            var IDataResolve = function () {\n                for (var prop in that) {\n                    if (that.hasOwnProperty(prop)) {\n                        this[prop] = that[prop];\n                    }\n                }\n            };\n            IDataResolve.prototype = {\n                is : IData.prototype.is,\n                toString : IData.prototype.toString,\n                withClientHints : IData.prototype.withClientHints,\n                withFeatureCheck : IData.prototype.withFeatureCheck\n            };\n            var resolveData = new IDataResolve();\n            cb(resolveData);\n            return resolveData;\n        };\n\n        return new IData();\n    };\n\n    /////////////////\n    // Constructor\n    ////////////////\n\n    function UACHData (uach, isHttpUACH) {\n        uach = uach || {};\n        setProps.call(this, CH_ALL_VALUES);\n        if (isHttpUACH) {\n            setProps.call(this, [\n                [BRANDS, itemListToArray(uach[CH])],\n                [FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],\n                [MOBILE, /\\?1/.test(uach[CH_MOBILE])],\n                [MODEL, stripQuotes(uach[CH_MODEL])],\n                [PLATFORM, stripQuotes(uach[CH_PLATFORM])],\n                [PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],\n                [ARCHITECTURE, stripQuotes(uach[CH_ARCH])],\n                [FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],\n                [BITNESS, stripQuotes(uach[CH_BITNESS])]\n            ]);\n        } else {\n            for (var prop in uach) {\n                if(this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];\n            }\n        }\n    }\n\n    function UAItem (itemType, ua, rgxMap, uaCH) {\n        setProps.call(this, [\n            ['itemType', itemType],\n            ['ua', ua],\n            ['uaCH', uaCH],\n            ['rgxMap', rgxMap],\n            ['data', createIData(this, itemType)]\n        ]);\n        return this;\n    }\n\n    UAItem.prototype.get = function (prop) {\n        if (!prop) return this.data;\n        return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;\n    };\n\n    UAItem.prototype.set = function (prop, val) {\n        this.data[prop] = val;\n        return this;\n    };\n\n    UAItem.prototype.setCH = function (ch) {\n        this.uaCH = ch;\n        return this;\n    };\n\n    UAItem.prototype.detectFeature = function () {\n        if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {\n            switch (this.itemType) {\n                case BROWSER:\n                    // Brave-specific detection\n                    if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {\n                        this.set(NAME, 'Brave');\n                    }\n                    break;\n                case DEVICE:\n                    // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData\n                    if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {\n                        this.set(TYPE, MOBILE);\n                    }\n                    // iPadOS-specific detection: identified as Mac, but has some iOS-only properties\n                    if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {\n                        this.set(MODEL, 'iPad')\n                            .set(TYPE, TABLET);\n                    }\n                    break;\n                case OS:\n                    // Chrome-specific detection: check for 'platform' value of navigator.userAgentData\n                    if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {\n                        this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);\n                    }\n                    break;\n                case RESULT:\n                    var data = this.data;\n                    var detect = function (itemType) {\n                        return data[itemType]\n                                .getItem()\n                                .detectFeature()\n                                .get();\n                    };\n                    this.set(BROWSER, detect(BROWSER))\n                        .set(CPU, detect(CPU))\n                        .set(DEVICE, detect(DEVICE))\n                        .set(ENGINE, detect(ENGINE))\n                        .set(OS, detect(OS));\n            }\n        }\n        return this;\n    };\n\n    UAItem.prototype.parseUA = function () {\n        if (this.itemType != RESULT) {\n            rgxMapper.call(this.data, this.ua, this.rgxMap);\n        }\n        switch (this.itemType) {\n            case BROWSER:\n                this.set(MAJOR, majorize(this.get(VERSION)));\n                break;\n            case OS:\n                // Since iOS 26, Safari's UA reports the OS version as frozen at 18:\n                // https://webkit.org/blog/17333/webkit-features-in-safari-26-0/#update-to-ua-string\n                if (this.get(NAME) == 'iOS' && this.get(VERSION)) {\n                    // Only perform this if iOS version is 18/19\n                    if (/^1[89][^\\d]/.exec(this.get(VERSION))) {\n                        // Based on the assumption that \"iOS\" version is tightly coupled with \"Safari\" version\n                        var realVersion = /\\) Version\\/((\\d+)[\\d\\.]*)/.exec(this.ua);\n                        if (realVersion && parseInt(realVersion[2], 10) >= 26) {\n                            // iOS version = Safari version\n                            this.set(VERSION, realVersion[1]);\n                        }\n                    }\n                }\n                break;\n        }\n        return this;\n    };\n\n    UAItem.prototype.parseCH = function () {\n        var uaCH = this.uaCH,\n            rgxMap = this.rgxMap;\n\n        switch (this.itemType) {\n            case BROWSER:\n            case ENGINE:\n                var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;\n                if (brands) {\n                    for (var i=0; i<brands.length; i++) {\n                        var brandName = brands[i].brand || brands[i],\n                            brandVersion = brands[i].version;\n                        if (this.itemType == BROWSER && \n                            !/not.a.brand/i.test(brandName) && \n                            (!prevName || \n                                (/Chrom/.test(prevName) && brandName != CHROMIUM) || \n                                (prevName == EDGE && /WebView2/.test(brandName))\n                            )) {\n                                brandName = strMapper(brandName, browserHintsMap);\n                                prevName = this.get(NAME);\n                                if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {\n                                    this.set(NAME, brandName)\n                                        .set(VERSION, brandVersion)\n                                        .set(MAJOR, majorize(brandVersion));\n                                }\n                                prevName = brandName;\n                        }\n                        if (this.itemType == ENGINE && brandName == CHROMIUM) {\n                            this.set(VERSION, brandVersion);\n                        }\n                    }\n                }\n                break;\n            case CPU:\n                var archName = uaCH[ARCHITECTURE];\n                if (archName) {\n                    if (archName && uaCH[BITNESS] == '64') archName += '64';\n                    rgxMapper.call(this.data, archName + ';', rgxMap);\n                }\n                break;\n            case DEVICE:\n                if (uaCH[MOBILE]) {\n                    this.set(TYPE, MOBILE);\n                }\n                if (uaCH[MODEL]) {\n                    this.set(MODEL, uaCH[MODEL]);\n                    if (!this.get(TYPE) || !this.get(VENDOR)) {\n                        var reParse = {};\n                        rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);\n                        if (!this.get(TYPE) && !!reParse.type) {\n                            this.set(TYPE, reParse.type);\n                        }\n                        if (!this.get(VENDOR) && !!reParse.vendor) {\n                            this.set(VENDOR, reParse.vendor);\n                        }\n                    }\n                }\n                if (uaCH[FORMFACTORS]) {\n                    var ff;\n                    if (typeof uaCH[FORMFACTORS] !== 'string') {\n                        var idx = 0;\n                        while (!ff && idx < uaCH[FORMFACTORS].length) {\n                            ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);\n                        }\n                    } else {\n                        ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);\n                    }\n                    this.set(TYPE, ff);\n                }\n                break;\n            case OS:\n                var osName = uaCH[PLATFORM];\n                if(osName) {\n                    var osVersion = uaCH[PLATFORMVER];\n                    if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');\n                    this.set(NAME, osName)\n                        .set(VERSION, osVersion);\n                }\n                // Xbox-Specific Detection\n                if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {\n                    this.set(NAME, 'Xbox')\n                        .set(VERSION, undefined);\n                }           \n                break;\n            case RESULT:\n                var data = this.data;\n                var parse = function (itemType) {\n                    return data[itemType]\n                            .getItem()\n                            .setCH(uaCH)\n                            .parseCH()\n                            .get();\n                };\n                this.set(BROWSER, parse(BROWSER))\n                    .set(CPU, parse(CPU))\n                    .set(DEVICE, parse(DEVICE))\n                    .set(ENGINE, parse(ENGINE))\n                    .set(OS, parse(OS));\n        }\n        return this;\n    };\n\n    function UAParser (ua, extensions, headers) {\n\n        if (typeof ua === TYPEOF.OBJECT) {\n            if (isExtensions(ua, true)) {\n                if (typeof extensions === TYPEOF.OBJECT) {\n                    headers = extensions;               // case UAParser(extensions, headers)           \n                }\n                extensions = ua;                        // case UAParser(extensions)\n            } else {\n                headers = ua;                           // case UAParser(headers)\n                extensions = undefined;\n            }\n            ua = undefined;\n        } else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {\n            headers = extensions;                       // case UAParser(ua, headers)\n            extensions = undefined;\n        }\n\n        if (headers) {\n            if (typeof headers.append === TYPEOF.FUNCTION) {\n                // Convert Headers object into a plain object\n                var kv = {};\n                headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; });\n                headers = kv;\n            } else {\n                // Normalize headers field name into lowercase\n                var normalized = {};\n                for (var header in headers) {\n                    if (headers.hasOwnProperty(header)) {\n                        normalized[String(header).toLowerCase()] = headers[header];\n                    }\n                }\n                headers = normalized;\n            }\n        }\n        \n        if (!(this instanceof UAParser)) {\n            return new UAParser(ua, extensions, headers).getResult();\n        }\n\n        var userAgent = typeof ua === TYPEOF.STRING ? ua :                                       // Passed user-agent string\n                                (headers && headers[USER_AGENT] ? headers[USER_AGENT] :     // User-Agent from passed headers\n                                ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent\n                                    EMPTY)),                                                // empty string\n\n            httpUACH = new UACHData(headers, true),\n            regexMap = defaultRegexes,\n\n            createItemFunc = function (itemType) {\n                if (itemType == RESULT) {\n                    return function () {\n                        return new UAItem(itemType, userAgent, regexMap, httpUACH)\n                                    .set('ua', userAgent)\n                                    .set(BROWSER, this.getBrowser())\n                                    .set(CPU, this.getCPU())\n                                    .set(DEVICE, this.getDevice())\n                                    .set(ENGINE, this.getEngine())\n                                    .set(OS, this.getOS())\n                                    .get();\n                    };\n                } else {\n                    return function () {\n                        return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)\n                                    .parseUA()\n                                    .get();\n                    };\n                }\n            };\n            \n        // public methods\n        setProps.call(this, [\n            ['getBrowser', createItemFunc(BROWSER)],\n            ['getCPU', createItemFunc(CPU)],\n            ['getDevice', createItemFunc(DEVICE)],\n            ['getEngine', createItemFunc(ENGINE)],\n            ['getOS', createItemFunc(OS)],\n            ['getResult', createItemFunc(RESULT)],\n            ['getUA', function () { return userAgent; }],\n            ['setUA', function (ua) {\n                if (isString(ua)) userAgent = trim(ua, UA_MAX_LENGTH);\n                return this;\n            }],\n            ['useExtension', function (exts) {\n                if (exts) regexMap = extend(regexMap, exts);\n                return this;\n            }]\n        ])\n        .setUA(userAgent)\n        .useExtension(extensions);\n\n        return this;\n    }\n\n    UAParser.VERSION = LIBVERSION;\n    UAParser.BROWSER =  enumerize([NAME, VERSION, MAJOR, TYPE]);\n    UAParser.CPU = enumerize([ARCHITECTURE]);\n    UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);\n    UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);\n\n    ///////////\n    // Export\n    //////////\n\n    // check js environment\n    if (typeof exports !== TYPEOF.UNDEFINED) {\n        // nodejs env\n        if (typeof module !== TYPEOF.UNDEFINED && module.exports) {\n            exports = module.exports = UAParser;\n        }\n        exports.UAParser = UAParser;\n    } else {\n        // requirejs env (optional)\n        if (typeof define === TYPEOF.FUNCTION && define.amd) {\n            define(function () {\n                return UAParser;\n            });\n        } else if (isWindow) {\n            // browser env\n            window.UAParser = UAParser;\n        }\n    }\n\n    // jQuery/Zepto specific (optional)\n    // Note:\n    //   In AMD env the global scope should be kept clean, but jQuery is an exception.\n    //   jQuery always exports to global scope, unless jQuery.noConflict(true) is used,\n    //   and we should catch that.\n    var $ = isWindow && (window.jQuery || window.Zepto);\n    if ($ && !$.ua) {\n        var parser = new UAParser();\n        $.ua = parser.getResult();\n        $.ua.get = function () {\n            return parser.getUA();\n        };\n        $.ua.set = function (ua) {\n            parser.setUA(ua);\n            var result = parser.getResult();\n            for (var prop in result) {\n                $.ua[prop] = result[prop];\n            }\n        };\n    }\n\n})(typeof window === 'object' ? window : this);\n"
  },
  {
    "path": "src/main/ua-parser.mjs",
    "content": "// Generated ESM version of ua-parser-js\n// DO NOT EDIT THIS FILE!\n// Source: /src/main/ua-parser.js\n\n/////////////////////////////////////////////////////////////////////////////////\n/* UAParser.js v2.0.9\n   Copyright © 2012-2026 Faisal Salman <f@faisalman.com>\n   AGPLv3 License *//*\n   Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.\n   Supports browser & node.js environment. \n   Demo   : https://uaparser.dev\n   Source : https://github.com/faisalman/ua-parser-js */\n/////////////////////////////////////////////////////////////////////////////////\n\n/* jshint esversion: 6 */ \n/* globals window */\n\n\n    \n    //////////////\n    // Constants\n    /////////////\n\n    var LIBVERSION  = '2.0.9',\n        UA_MAX_LENGTH = 500,\n        USER_AGENT  = 'user-agent',\n        EMPTY       = '',\n        UNKNOWN     = '?',\n        TYPEOF = {\n            FUNCTION    : 'function',\n            OBJECT      : 'object',\n            STRING      : 'string',\n            UNDEFINED   : 'undefined'\n        },\n\n        // properties\n        BROWSER     = 'browser',\n        CPU         = 'cpu',\n        DEVICE      = 'device',\n        ENGINE      = 'engine',\n        OS          = 'os',\n        RESULT      = 'result',\n\n        NAME        = 'name',\n        TYPE        = 'type',\n        VENDOR      = 'vendor',\n        VERSION     = 'version',\n        ARCHITECTURE= 'architecture',\n        MAJOR       = 'major',\n        MODEL       = 'model',\n\n        // device types\n        CONSOLE     = 'console',\n        MOBILE      = 'mobile',\n        TABLET      = 'tablet',\n        SMARTTV     = 'smarttv',\n        WEARABLE    = 'wearable',\n        XR          = 'xr',\n        EMBEDDED    = 'embedded',\n\n        // browser types\n        FETCHER     = 'fetcher',\n        INAPP       = 'inapp',\n\n        // client hints\n        BRANDS      = 'brands',\n        FORMFACTORS = 'formFactors',\n        FULLVERLIST = 'fullVersionList',\n        PLATFORM    = 'platform',\n        PLATFORMVER = 'platformVersion',\n        BITNESS     = 'bitness',\n        CH          = 'sec-ch-ua',\n        CH_FULL_VER_LIST= CH + '-full-version-list',\n        CH_ARCH         = CH + '-arch',\n        CH_BITNESS      = CH + '-' + BITNESS,\n        CH_FORM_FACTORS = CH + '-form-factors',\n        CH_MOBILE       = CH + '-' + MOBILE,\n        CH_MODEL        = CH + '-' + MODEL,\n        CH_PLATFORM     = CH + '-' + PLATFORM,\n        CH_PLATFORM_VER = CH_PLATFORM + '-version',\n        CH_ALL_VALUES   = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS],\n\n        // device vendors\n        AMAZON      = 'Amazon',\n        APPLE       = 'Apple',\n        ASUS        = 'ASUS',\n        BLACKBERRY  = 'BlackBerry',\n        GOOGLE      = 'Google',\n        HUAWEI      = 'Huawei',\n        LENOVO      = 'Lenovo',\n        HONOR       = 'Honor',\n        LG          = 'LG',\n        MICROSOFT   = 'Microsoft',\n        MOTOROLA    = 'Motorola',\n        NVIDIA      = 'Nvidia',\n        ONEPLUS     = 'OnePlus',\n        OPPO        = 'OPPO',\n        SAMSUNG     = 'Samsung',\n        SHARP       = 'Sharp',\n        SONY        = 'Sony',\n        XIAOMI      = 'Xiaomi',\n        ZEBRA       = 'Zebra',\n\n        // browsers\n        CHROME      = 'Chrome',\n        CHROMIUM    = 'Chromium',\n        CHROMECAST  = 'Chromecast',\n        EDGE        = 'Edge',\n        FIREFOX     = 'Firefox',\n        OPERA       = 'Opera',\n        FACEBOOK    = 'Facebook',\n        SOGOU       = 'Sogou',\n\n        PREFIX_MOBILE  = 'Mobile ',\n        SUFFIX_BROWSER = ' Browser',\n\n        // os\n        WINDOWS     = 'Windows';\n   \n    var isWindow            = typeof window !== TYPEOF.UNDEFINED,\n        NAVIGATOR           = (isWindow && window.navigator) ? \n                                window.navigator : \n                                undefined,\n        NAVIGATOR_UADATA    = (NAVIGATOR && NAVIGATOR.userAgentData) ? \n                                NAVIGATOR.userAgentData : \n                                undefined;\n\n    ///////////\n    // Helper\n    //////////\n\n    var extend = function (defaultRgx, extensions) {\n            var mergedRgx = {};\n            var extraRgx = extensions;\n            if (!isExtensions(extensions)) {\n                extraRgx = {};\n                for (var i in extensions) {\n                    for (var j in extensions[i]) {\n                        extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);\n                    }\n                }\n            }\n            for (var k in defaultRgx) {\n                mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];\n            }\n            return mergedRgx;\n        },\n        enumerize = function (arr) {\n            var enums = {};\n            for (var i=0; i<arr.length; i++) {\n                enums[arr[i].toUpperCase()] = arr[i];\n            }\n            return enums;\n        },\n        has = function (str1, str2) {\n            if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {\n                for (var i in str1) {\n                    if (lowerize(str2) == lowerize(str1[i])) return true;\n                }\n                return false;\n            }\n            return isString(str1) ? lowerize(str2) == lowerize(str1) : false;\n        },\n        isExtensions = function (obj, deep) {\n            for (var prop in obj) {\n                return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);\n            }\n        },\n        isString = function (val) {\n            return typeof val === TYPEOF.STRING;\n        },\n        itemListToArray = function (header) {\n            if (!header) return undefined;\n            var arr = [];\n            var tokens = strip(/\\\\?\\\"/g, header).split(',');\n            for (var i = 0; i < tokens.length; i++) {\n                if (tokens[i].indexOf(';') > -1) {\n                    var token = trim(tokens[i]).split(';v=');\n                    arr[i] = { brand : token[0], version : token[1] };\n                } else {\n                    arr[i] = trim(tokens[i]);\n                }\n            }\n            return arr;\n        },\n        lowerize = function (str) {\n            return isString(str) ? str.toLowerCase() : str;\n        },\n        majorize = function (version) {\n            return isString(version) ? strip(/[^\\d\\.]/g, version).split('.')[0] : undefined;\n        },\n        setProps = function (arr) {\n            for (var i in arr) {\n                if (!arr.hasOwnProperty(i)) continue;\n\n                var propName = arr[i];\n                if (typeof propName == TYPEOF.OBJECT && propName.length == 2) {\n                    this[propName[0]] = propName[1];\n                } else {\n                    this[propName] = undefined;\n                }\n            }\n            return this;\n        },\n        strip = function (pattern, str) {\n            return isString(str) ? str.replace(pattern, EMPTY) : str;\n        },\n        stripQuotes = function (str) {\n            return strip(/\\\\?\\\"/g, str); \n        },\n        trim = function (str, len) {\n            str = strip(/^\\s\\s*/, String(str));\n            return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);\n    };\n\n    ///////////////\n    // Map helper\n    //////////////\n\n    var rgxMapper = function (ua, arrays) {\n\n            if(!ua || !arrays) return;\n\n            var i = 0, j, k, p, q, matches, match;\n\n            // loop through all regexes maps\n            while (i < arrays.length && !matches) {\n\n                var regex = arrays[i],       // even sequence (0,2,4,..)\n                    props = arrays[i + 1];   // odd sequence (1,3,5,..)\n                j = k = 0;\n\n                // try matching uastring with regexes\n                while (j < regex.length && !matches) {\n\n                    if (!regex[j]) { break; }\n                    matches = regex[j++].exec(ua);\n\n                    if (!!matches) {\n                        for (p = 0; p < props.length; p++) {\n                            match = matches[++k];\n                            q = props[p];\n                            // check if given property is actually array\n                            if (typeof q === TYPEOF.OBJECT && q.length > 0) {\n                                if (q.length === 2) {\n                                    if (typeof q[1] == TYPEOF.FUNCTION) {\n                                        // assign modified match\n                                        this[q[0]] = q[1].call(this, match);\n                                    } else {\n                                        // assign given value, ignore regex match\n                                        this[q[0]] = q[1];\n                                    }\n                                } else if (q.length >= 3) {\n                                    // Check whether q[1] FUNCTION or REGEX\n                                    if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) {\n                                        if (q.length > 3) {\n                                            this[q[0]] = match ? q[1].apply(this, q.slice(2)) : undefined;\n                                        } else {\n                                            // call function (usually string mapper)\n                                            this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n                                        }\n                                    } else {\n                                        if (q.length == 3) {\n                                            // sanitize match using given regex\n                                            this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n                                        } else if (q.length == 4) {\n                                            this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n                                        } else if (q.length > 4) {\n                                            this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : undefined;\n                                        }\n                                    }\n                                }\n                            } else {\n                                this[q] = match ? match : undefined;\n                            }\n                        }\n                    }\n                }\n                i += 2;\n            }\n        },\n\n        strMapper = function (str, map) {\n\n            for (var i in map) {\n                // check if current value is array\n                if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {\n                    for (var j = 0; j < map[i].length; j++) {\n                        if (has(map[i][j], str)) {\n                            return (i === UNKNOWN) ? undefined : i;\n                        }\n                    }\n                } else if (has(map[i], str)) {\n                    return (i === UNKNOWN) ? undefined : i;\n                }\n            }\n            return map.hasOwnProperty('*') ? map['*'] : str;\n    };\n\n    ///////////////\n    // String map\n    //////////////\n\n    var windowsVersionMap = {\n            'ME'    : '4.90',\n            'NT 3.51': '3.51',\n            'NT 4.0': '4.0',\n            '2000'  : ['5.0', '5.01'],\n            'XP'    : ['5.1', '5.2'],\n            'Vista' : '6.0',\n            '7'     : '6.1',\n            '8'     : '6.2',\n            '8.1'   : '6.3',\n            '10'    : ['6.4', '10.0'],\n            'NT'    : ''\n        },\n        \n        formFactorsMap = {\n            'embedded'  : 'Automotive',\n            'mobile'    : 'Mobile',\n            'tablet'    : ['Tablet', 'EInk'],\n            'smarttv'   : 'TV',\n            'wearable'  : 'Watch',\n            'xr'        : ['VR', 'XR'],\n            '?'         : ['Desktop', 'Unknown'],\n            '*'         : undefined\n        },\n\n        browserHintsMap = {\n            'Chrome'        : 'Google Chrome',\n            'Edge'          : 'Microsoft Edge',\n            'Edge WebView2' : 'Microsoft Edge WebView2',\n            'Chrome WebView': 'Android WebView',\n            'Chrome Headless':'HeadlessChrome',\n            'Huawei Browser': 'HuaweiBrowser',\n            'MIUI Browser'  : 'Miui Browser',\n            'Opera Mobi'    : 'OperaMobile',\n            'Yandex'        : 'YaBrowser'\n    };\n\n    //////////////\n    // Regex map\n    /////////////\n\n    var defaultRegexes = {\n\n        browser : [[\n\n            // Most common regardless engine\n            /\\b(?:crmo|crios)\\/([\\w\\.]+)/i                                      // Chrome for Android/iOS\n            ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [\n            /webview.+edge\\/([\\w\\.]+)/i                                         // Microsoft Edge\n            ], [VERSION, [NAME, EDGE+' WebView']], [\n            /edg(?:e|ios|a)?\\/([\\w\\.]+)/i                                       \n            ], [VERSION, [NAME, 'Edge']], [\n\n            // Presto based\n            /(opera mini)\\/([-\\w\\.]+)/i,                                        // Opera Mini\n            /(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i,                 // Opera Mobi/Tablet\n            /(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i                           // Opera\n            ], [NAME, VERSION], [\n            /opios[\\/ ]+([\\w\\.]+)/i                                             // Opera mini on iphone >= 8.0\n            ], [VERSION, [NAME, OPERA+' Mini']], [\n            /\\bop(?:rg)?x\\/([\\w\\.]+)/i                                          // Opera GX\n            ], [VERSION, [NAME, OPERA+' GX']], [\n            /\\bopr\\/([\\w\\.]+)/i                                                 // Opera Webkit\n            ], [VERSION, [NAME, OPERA]], [\n\n            // Mixed\n            /\\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\\/ ]?([\\w\\.]+)/i            // Baidu\n            ], [VERSION, [NAME, 'Baidu']], [\n            /\\b(?:mxbrowser|mxios|myie2)\\/?([-\\w\\.]*)\\b/i                       // Maxthon\n            ], [VERSION, [NAME, 'Maxthon']], [\n            /(kindle)\\/([\\w\\.]+)/i,                                             // Kindle\n            /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\\/ ]?([\\w\\.]*)/i,      \n                                                                                // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir\n            // Trident based\n            /(avant|iemobile|slim(?:browser|boat|jet))[\\/ ]?([\\d\\.]*)/i,        // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet\n            /(?:ms|\\()(ie) ([\\w\\.]+)/i,                                         // Internet Explorer\n\n            // Blink/Webkit/KHTML based                                         // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon/HiBrowser\n            /(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\\/v?([-\\w\\.]+)/i,\n                                                                                // Atlas/Rekonq/Puffin/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon\n            /(brave)(?: chrome)?\\/([\\d\\.]+)/i,                                  // Brave\n            /(aloha|heytap|ovi|115|surf|qwant)browser\\/([\\d\\.]+)/i,             // Aloha/HeyTap/Ovi/115/Surf\n            /(qwant)(?:ios|mobile)\\/([\\d\\.]+)/i,                                // Qwant\n            /(ecosia|weibo)(?:__| \\w+@)([\\d\\.]+)/i                              // Ecosia/Weibo\n            ], [NAME, VERSION], [\n            /quark(?:pc)?\\/([-\\w\\.]+)/i                                         // Quark\n            ], [VERSION, [NAME, 'Quark']], [\n            /\\bddg\\/([\\w\\.]+)/i                                                 // DuckDuckGo\n            ], [VERSION, [NAME, 'DuckDuckGo']], [\n            /(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i                 // UCBrowser\n            ], [VERSION, [NAME, 'UCBrowser']], [\n            /microm.+\\bqbcore\\/([\\w\\.]+)/i,                                     // WeChat Desktop for Windows Built-in Browser\n            /\\bqbcore\\/([\\w\\.]+).+microm/i,\n            /micromessenger\\/([\\w\\.]+)/i                                        // WeChat\n            ], [VERSION, [NAME, 'WeChat']], [\n            /konqueror\\/([\\w\\.]+)/i                                             // Konqueror\n            ], [VERSION, [NAME, 'Konqueror']], [\n            /trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i                       // IE11\n            ], [VERSION, [NAME, 'IE']], [\n            /ya(?:search)?browser\\/([\\w\\.]+)/i                                  // Yandex\n            ], [VERSION, [NAME, 'Yandex']], [\n            /slbrowser\\/([\\w\\.]+)/i                                             // Smart Lenovo Browser\n            ], [VERSION, [NAME, 'Smart ' + LENOVO + SUFFIX_BROWSER]], [\n            /(av(?:ast|g|ira))\\/([\\w\\.]+)/i                                     // Avast/AVG/Avira Secure Browser\n            ], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [\n            /norton\\/([\\w\\.]+)/i                                                // Norton Private Browser\n            ], [VERSION, [NAME, 'Norton Private' + SUFFIX_BROWSER]], [\n            /\\bfocus\\/([\\w\\.]+)/i                                               // Firefox Focus\n            ], [VERSION, [NAME, FIREFOX+' Focus']], [\n            / mms\\/([\\w\\.]+)$/i                                                 // Opera Neon\n            ], [VERSION, [NAME, OPERA+' Neon']], [\n            / opt\\/([\\w\\.]+)$/i                                                 // Opera Touch\n            ], [VERSION, [NAME, OPERA+' Touch']], [\n            /coc_coc\\w+\\/([\\w\\.]+)/i                                            // Coc Coc Browser\n            ], [VERSION, [NAME, 'Coc Coc']], [\n            /dolfin\\/([\\w\\.]+)/i                                                // Dolphin\n            ], [VERSION, [NAME, 'Dolphin']], [\n            /coast\\/([\\w\\.]+)/i                                                 // Opera Coast\n            ], [VERSION, [NAME, OPERA+' Coast']], [\n            /miuibrowser\\/([\\w\\.]+)/i                                           // MIUI Browser\n            ], [VERSION, [NAME, 'MIUI' + SUFFIX_BROWSER]], [\n            /fxios\\/([\\w\\.-]+)/i                                                // Firefox for iOS\n            ], [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]], [\n            /\\bqihoobrowser\\/?([\\w\\.]*)/i                                       // 360\n            ], [VERSION, [NAME, '360']], [\n            /\\b(qq)\\/([\\w\\.]+)/i                                                // QQ\n            ], [[NAME, /(.+)/, '$1Browser'], VERSION], [\n            /(oculus|sailfish|huawei|vivo|pico)browser\\/([\\w\\.]+)/i\n            ], [[NAME, /(.+)/, '$1' + SUFFIX_BROWSER], VERSION], [              // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser\n            /samsungbrowser\\/([\\w\\.]+)/i                                        // Samsung Internet\n            ], [VERSION, [NAME, SAMSUNG + ' Internet']], [\n            /metasr[\\/ ]?([\\d\\.]+)/i                                            // Sogou Explorer\n            ], [VERSION, [NAME, SOGOU + ' Explorer']], [\n            /(sogou)mo\\w+\\/([\\d\\.]+)/i                                          // Sogou Mobile\n            ], [[NAME, SOGOU + ' Mobile'], VERSION], [\n            /(electron)\\/([\\w\\.]+) safari/i,                                    // Electron-based App\n            /(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i,                   // Tesla\n            /m?(qqbrowser|2345(?=browser|chrome|explorer))\\w*[\\/ ]?v?([\\w\\.]+)/i   // QQ/2345\n            ], [NAME, VERSION], [\n            /(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i            // LieBao Browser/Luakit/Rekonq/Steam\n            ], [NAME], [\n            /ome\\/([\\w\\.]+).+(iron(?= saf)|360(?=[es]e$))/i                     // Iron / 360\n            ], [VERSION, NAME], [\n\n            // WebView\n            /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i       // Facebook App for iOS & Android\n            ], [[NAME, FACEBOOK], VERSION, [TYPE, INAPP]], [\n            /(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i,                             // Kakao App\n            /(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i,                                  // Naver InApp\n            /(daum)apps[\\/ ]([\\w\\.]+)/i,                                        // Daum App\n            /safari (line)\\/([\\w\\.]+)/i,                                        // Line App for iOS\n            /\\b(line)\\/([\\w\\.]+)\\/iab/i,                                        // Line App for Android\n            /(alipay)client\\/([\\w\\.]+)/i,                                       // Alipay\n            /(twitter)(?:and| f.+e\\/([\\w\\.]+))/i,                               // Twitter\n            /(bing)(?:web|sapphire)\\/([\\w\\.]+)/i,                               // Bing\n            /(instagram|snapchat|klarna)[\\/ ]([-\\w\\.]+)/i                       // Instagram/Snapchat/Klarna\n            ], [NAME, VERSION, [TYPE, INAPP]], [\n            /\\bgsa\\/([\\w\\.]+) .*safari\\//i                                      // Google Search Appliance on iOS\n            ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [\n            /(?:musical_ly|trill)(?:.+app_?version\\/|_)([\\w\\.]+)/i              // TikTok\n            ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [\n            /\\[(linkedin)app\\]/i                                                // LinkedIn App for iOS & Android\n            ], [NAME, [TYPE, INAPP]], [\n            /(zalo(?:app)?)[\\/\\sa-z]*([\\w\\.-]+)/i                               // Zalo \n            ], [[NAME, /(.+)/, 'Zalo'], VERSION, [TYPE, INAPP]], [\n\n            /(chromium)[\\/ ]([-\\w\\.]+)/i                                        // Chromium\n            ], [NAME, VERSION], [\n\n            /ome-(lighthouse)$/i                                                // Chrome Lighthouse\n            ], [NAME, [TYPE, FETCHER]], [\n\n            /headlesschrome(?:\\/([\\w\\.]+)| )/i                                  // Chrome Headless\n            ], [VERSION, [NAME, CHROME+' Headless']], [\n\n            /wv\\).+chrome\\/([\\w\\.]+).+edgw\\//i                                  // Edge WebView2\n            ], [VERSION, [NAME, EDGE+' WebView2']], [\n\n            / wv\\).+(chrome)\\/([\\w\\.]+)/i                                       // Chrome WebView\n            ], [[NAME, CHROME+' WebView'], VERSION], [\n\n            /droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i           // Android Browser\n            ], [VERSION, [NAME, 'Android' + SUFFIX_BROWSER]], [\n\n            /chrome\\/([\\w\\.]+) mobile/i                                         // Chrome Mobile\n            ], [VERSION, [NAME, PREFIX_MOBILE + 'Chrome']], [\n\n            /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i       // Chrome/OmniWeb/Arora/Tizen/Nokia\n            ], [NAME, VERSION], [\n\n            /version\\/([\\w\\.\\,]+) .*mobile(?:\\/\\w+ | ?)safari/i                 // Safari Mobile\n            ], [VERSION, [NAME, PREFIX_MOBILE + 'Safari']], [\n            /iphone .*mobile(?:\\/\\w+ | ?)safari/i\n            ], [[NAME, PREFIX_MOBILE + 'Safari']], [\n            /version\\/([\\w\\.\\,]+) .*(safari)/i                                  // Safari\n            ], [VERSION, NAME], [\n            /webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i                      // Safari < 3.0\n            ], [NAME, [VERSION, '1']], [\n\n            /(webkit|khtml)\\/([\\w\\.]+)/i\n            ], [NAME, VERSION], [\n\n            // Gecko based\n            /(?:mobile|tablet);.*(firefox)\\/([\\w\\.-]+)/i                        // Firefox Mobile\n            ], [[NAME, PREFIX_MOBILE + FIREFOX], VERSION], [\n            /(navigator|netscape\\d?)\\/([-\\w\\.]+)/i                              // Netscape\n            ], [[NAME, 'Netscape'], VERSION], [\n            /(wolvic|librewolf)\\/([\\w\\.]+)/i                                    // Wolvic/LibreWolf\n            ], [NAME, VERSION], [\n            /mobile vr; rv:([\\w\\.]+)\\).+firefox/i                               // Firefox Reality\n            ], [VERSION, [NAME, FIREFOX+' Reality']], [\n            /ekiohf.+(flow)\\/([\\w\\.]+)/i,                                       // Flow\n            /(swiftfox)/i,                                                      // Swiftfox\n            /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\\/ ]?([\\w\\.\\+]+)/i,\n                                                                                // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n            /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\\/([-\\w\\.]+)$/i,\n                                                                                // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n            /(firefox)\\/([\\w\\.]+)/i,                                            // Other Firefox-based\n            /(mozilla)\\/([\\w\\.]+(?= .+rv\\:.+gecko\\/\\d+)|[0-4][\\w\\.]+(?!.+compatible))/i, // Mozilla\n\n            // Other\n            /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,\n                                                                                // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser/Ladybird\n            /\\b(links) \\(([\\w\\.]+)/i                                            // Links\n            ], [NAME, [VERSION, /_/g, '.']], [\n            \n            /(cobalt)\\/([\\w\\.]+)/i                                              // Cobalt\n            ], [NAME, [VERSION, /[^\\d\\.]+./, EMPTY]]\n        ],\n\n        cpu : [[\n\n            /\\b((amd|x|x86[-_]?|wow|win)64)\\b/i                                 // AMD64 (x64)\n            ], [[ARCHITECTURE, 'amd64']], [\n\n            /(ia32(?=;))/i,                                                     // IA32 (quicktime)\n            /\\b((i[346]|x)86)(pc)?\\b/i                                          // IA32 (x86)\n            ], [[ARCHITECTURE, 'ia32']], [\n\n            /\\b(aarch64|arm(v?[89]e?l?|_?64))\\b/i                               // ARM64\n            ], [[ARCHITECTURE, 'arm64']], [\n\n            /\\b(arm(v[67])?ht?n?[fl]p?)\\b/i                                     // ARMHF\n            ], [[ARCHITECTURE, 'armhf']], [\n\n            // PocketPC mistakenly identified as PowerPC\n            /( (ce|mobile); ppc;|\\/[\\w\\.]+arm\\b)/i\n            ], [[ARCHITECTURE, 'arm']], [\n\n            / sun4\\w[;\\)]/i                                                     // SPARC\n            ], [[ARCHITECTURE, 'sparc']], [\n                                                                                // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n            /\\b(avr32|ia64(?=;)|68k(?=\\))|\\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\\b|pa-risc)/i,\n            /((ppc|powerpc)(64)?)( mac|;|\\))/i,                                 // PowerPC\n            /(?:osf1|[freopnt]{3,4}bsd) (alpha)/i                               // Alpha\n            ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [\n            /mc680.0/i\n            ], [[ARCHITECTURE, '68k']], [\n            /winnt.+\\[axp/i\n            ], [[ARCHITECTURE, 'alpha']]\n        ],\n\n        device : [[\n\n            //////////////////////////\n            // MOBILES & TABLETS\n            /////////////////////////\n\n            // Samsung\n            /\\b(sch-i[89]0\\d|shw-m380s|sm-[ptx]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus 10)/i\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [\n            /\\b((?:s[cgp]h|gt|sm)-(?![lr])\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,\n            /samsung[- ]((?!sm-[lr]|browser)[-\\w]+)/i,\n            /sec-(sgh\\w+)/i\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [\n\n            // Apple\n            /(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)[\\/\\);]/i                           // iPod/iPhone\n            ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [\n            /\\b(?:ios|apple\\w+)\\/.+[\\(\\/](ipad)/i,                              // iPad\n            /\\b(ipad)[\\d,]*[;\\] ].+(mac |i(pad)?)os/i\n            ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [\n            /(macintosh);/i\n            ], [MODEL, [VENDOR, APPLE]], [\n\n            // Sharp\n            /\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i\n            ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [\n\n            // Honor\n            /\\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\\)|;)/i\n            ], [MODEL, [VENDOR, HONOR], [TYPE, TABLET]], [\n            /honor([-\\w ]+)[;\\)]/i\n            ], [MODEL, [VENDOR, HONOR], [TYPE, MOBILE]], [\n\n            // Huawei\n            /\\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\\w\\. ]*(?= bui|\\)))\\b(?!.+d\\/s)/i\n            ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [\n            /(?:huawei) ?([-\\w ]+)[;\\)]/i,\n            /\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][\\dc][adnt]?)\\b(?!.+d\\/s)/i\n            ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [\n\n            // Xiaomi\n            /oid[^\\)]+; (2[\\dbc]{4}(182|283|rp\\w{2})[cgl]|m2105k81a?c)(?: bui|\\))/i,\n            /\\b(?:xiao)?((?:red)?mi[-_ ]?pad[\\w- ]*)(?: bui|\\))/i               // Mi Pad tablets\n            ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [\n\n            /\\b; (\\w+) build\\/hm\\1/i,                                           // Xiaomi Hongmi 'numeric' models\n            /\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i,                             // Xiaomi Hongmi\n                                                                                // Xiaomi Redmi / POCO / Black Shark / Qin\n            /oid[^\\)]+; (redmi[\\-_ ]?(?:note|k)?[\\w_ ]+|m?[12]\\d[01]\\d\\w{3,6}|poco[\\w ]+|(shark )?\\w{3}-[ah]0|qin ?[1-3](s\\+|ultra| pro)?)( bui|; wv|\\))/i,\n                                                                                // Xiaomi Mi\n            /\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\\d{0,2}\\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\\))/i,\n            / ([\\w ]+) miui\\/v?\\d/i\n            ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [\n\n            // OnePlus\n            /droid.+; (cph2[3-6]\\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\\d|p[g-l]\\w[1m]10)\\b/i,\n            /(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i\n            ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [\n\n            // OPPO\n            /; (\\w+) bui.+ oppo/i,\n            /\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i\n            ], [MODEL, [VENDOR, OPPO], [TYPE, MOBILE]], [\n            /\\b(opd2(\\d{3}a?))(?: bui|\\))/i\n            ], [MODEL, [VENDOR, strMapper, { 'OnePlus' : ['203', '304', '403', '404', '413', '415'], '*' : OPPO }], [TYPE, TABLET]], [\n\n            // BLU\n            /(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\\w\\+ ]*)(?: bui|\\))/i  // Vivo series\n            ], [MODEL, [VENDOR, 'BLU'], [TYPE, MOBILE]], [    \n\n            // Vivo\n            /; vivo (\\w+)(?: bui|\\))/i,\n            /\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i\n            ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n            // Realme\n            /\\b(rmx[1-3]\\d{3})(?: bui|;|\\))/i\n            ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n            // Lenovo\n            /(ideatab[-\\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\\d{3,4}(?:f[cu]|xu|[av])|yt\\d?-[jx]?\\d+[lfmx])( bui|;|\\)|\\/)/i,\n            /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\\w- ]+?)|tb[\\w-]{6,7})( bui|;|\\)|\\/)/i\n            ], [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]], [            \n            /lenovo[-_ ]?([-\\w ]+?)(?: bui|\\)|\\/)/i\n            ], [MODEL, [VENDOR, LENOVO], [TYPE, MOBILE]], [\n\n            // Motorola\n            /\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,\n            /\\bmot(?:orola)?[- ]([\\w\\s]+)(\\)| bui)/i,\n            /((?:moto(?! 360)[-\\w\\(\\) ]+|xt\\d{3,4}[cgkosw\\+]?[-\\d]*|nexus 6)(?= bui|\\)))/i\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [\n            /\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [\n\n            // LG\n            /\\b(?:lg)?([vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i\n            ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [\n            /(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,\n            /\\blg[-e;\\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\\w+)/i,\n            /\\blg-?([\\d\\w]+) bui/i\n            ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [\n\n            // Nokia\n            /(nokia) (t[12][01])/i\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n            /(?:maemo|nokia).*(n900|lumia \\d+|rm-\\d+)/i,\n            /nokia[-_ ]?(([-\\w\\. ]*?))( bui|\\)|;|\\/)/i\n            ], [[MODEL, /_/g, ' '], [TYPE, MOBILE], [VENDOR, 'Nokia']], [\n\n            // Google\n            /(pixel (c|tablet))\\b/i                                             // Google Pixel C/Tablet\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [\n                                                                                // Google Pixel\n            /droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\\d ]*a?( pro)?( xl)?( fold)?( \\(5g\\))?)( bui|\\))/i\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [\n            /(google) (pixelbook( go)?)/i\n            ], [VENDOR, MODEL], [\n\n            // Sony\n            /droid.+; (a?\\d[0-2]{2}so|[c-g]\\d{4}|so[-gl]\\w+|xq-\\w\\w\\d\\d)(?= bui|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i\n            ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [\n            /sony tablet [ps]/i,\n            /\\b(?:sony)?sgp\\w+(?: bui|\\))/i\n            ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [\n\n            // Amazon\n            /(alexa)webm/i,\n            /(kf[a-z]{2}wi|aeo(?!bc)\\w\\w)( bui|\\))/i,                           // Kindle Fire without Silk / Echo Show\n            /(kf[a-z]+)( bui|\\)).+silk\\//i                                      // Kindle Fire HD\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [\n            /((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i                     // Fire Phone\n            ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [\n\n            // BlackBerry\n            /(playbook);[-\\w\\),; ]+(rim)/i                                      // BlackBerry PlayBook\n            ], [MODEL, VENDOR, [TYPE, TABLET]], [\n            /\\b((?:bb[a-f]|st[hv])100-\\d)/i,\n            /(?:blackberry|\\(bb10;) (\\w+)/i\n            ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [\n\n            // Asus\n            /(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i\n            ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [\n            / (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i\n            ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [\n\n            // HTC\n            /(nexus 9)/i                                                        // HTC Nexus 9\n            ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n            /(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i,                         // HTC\n\n            // ZTE\n            /(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,\n            /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i         // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n            ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n            // TCL\n            /tcl (xess p17aa)/i,\n            /droid [\\w\\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\\w(\\w|\\w\\w))?(\\)| bui)/i\n            ], [MODEL, [VENDOR, 'TCL'], [TYPE, TABLET]], [\n            /droid [\\w\\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\\w(\\w|\\w\\w))?(\\)| bui)/i\n            ], [MODEL, [VENDOR, 'TCL'], [TYPE, MOBILE]], [\n\n            // itel\n            /(itel) ((\\w+))/i\n            ], [[VENDOR, lowerize], MODEL, [TYPE, strMapper, { 'tablet' : ['p10001l', 'w7001'], '*' : 'mobile' }]], [\n\n            // Acer\n            /droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i\n            ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n            // Meizu\n            /droid.+; (m[1-5] note) bui/i,\n            /\\bmz-([-\\w]{2,})/i\n            ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n                \n            // Ulefone\n            /; ((?:power )?armor(?:[\\w ]{0,8}))(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Ulefone'], [TYPE, MOBILE]], [\n\n            // Energizer\n            /; (energy ?\\w+)(?: bui|\\))/i,\n            /; energizer ([\\w ]+)(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Energizer'], [TYPE, MOBILE]], [\n\n            // Cat\n            /; cat (b35);/i,\n            /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Cat'], [TYPE, MOBILE]], [\n\n            // Smartfren\n            /((?:new )?andromax[\\w- ]+)(?: bui|\\))/i\n            ], [MODEL, [VENDOR, 'Smartfren'], [TYPE, MOBILE]], [\n\n            // Nothing\n            /droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i\n            ], [MODEL, [VENDOR, 'Nothing'], [TYPE, MOBILE]], [\n\n            // Archos\n            /; (x67 5g|tikeasy \\w+|ac[1789]\\d\\w+)( b|\\))/i,\n            /archos ?(5|gamepad2?|([\\w ]*[t1789]|hello) ?\\d+[\\w ]*)( b|\\))/i\n            ], [MODEL, [VENDOR, 'Archos'], [TYPE, TABLET]], [\n            /archos ([\\w ]+)( b|\\))/i,\n            /; (ac[3-6]\\d\\w{2,8})( b|\\))/i \n            ], [MODEL, [VENDOR, 'Archos'], [TYPE, MOBILE]], [\n\n            // HMD\n            /; (n159v)/i\n            ], [MODEL, [VENDOR, 'HMD'], [TYPE, MOBILE]], [\n\n            // MIXED\n            /(imo) (tab \\w+)/i,                                                 // IMO\n            /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i                     // Infinix XPad / Tecno\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n            /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\\w]*)/i,\n                                                                                // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron/Tecno/Micromax/Advan\n                                                                                // BLU/HMD/IMO/Infinix/Lava/OnePlus/TCL/Wiko\n            /; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\\w\\+ ]+?)(?: bui|\\)|; r)/i,\n            /(hp) ([\\w ]+\\w)/i,                                                 // HP iPAQ\n            /(microsoft); (lumia[\\w ]+)/i,                                      // Microsoft Lumia\n            /(oppo) ?([\\w ]+) bui/i,                                            // OPPO\n            /(hisense) ([ehv][\\w ]+)\\)/i,                                       // Hisense\n            /droid[^;]+; (philips)[_ ]([sv-x][\\d]{3,4}[xz]?)/i                  // Philips\n            ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n            /(kobo)\\s(ereader|touch)/i,                                         // Kobo\n            /(hp).+(touchpad(?!.+tablet)|tablet)/i,                             // HP TouchPad\n            /(kindle)\\/([\\w\\.]+)/i                                              // Kindle\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n            /(surface duo)/i                                                    // Surface Duo\n            ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [\n            /droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i                                 // Fairphone\n            ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n            /((?:tegranote|shield t(?!.+d tv))[\\w- ]*?)(?: b|\\))/i              // Nvidia Tablets\n            ], [MODEL, [VENDOR, NVIDIA], [TYPE, TABLET]], [\n            /(sprint) (\\w+)/i                                                   // Sprint Phones\n            ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n            /(kin\\.[onetw]{3})/i                                                // Microsoft Kin\n            ], [[MODEL, /\\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [\n            /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i               // Zebra\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [\n            /droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [\n\n            ///////////////////\n            // SMARTTVS\n            ///////////////////\n\n            /(philips)[\\w ]+tv/i,                                               // Philips\n            /smart-tv.+(samsung)/i                                              // Samsung\n            ], [VENDOR, [TYPE, SMARTTV]], [\n            /hbbtv.+maple;(\\d+)/i\n            ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [\n            /(vizio)(?: |.+model\\/)(\\w+-\\w+)/i,                                 // Vizio\n            /tcast.+(lg)e?. ([-\\w]+)/i                                          // LG SmartTV\n            ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n            /(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i\n            ], [[VENDOR, LG], [TYPE, SMARTTV]], [\n            /(apple) ?tv/i                                                      // Apple TV\n            ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [\n            /crkey.*devicetype\\/chromecast/i                                    // Google Chromecast Third Generation\n            ], [[MODEL, CHROMECAST+' Third Generation'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /crkey.*devicetype\\/([^/]*)/i                                       // Google Chromecast with specific device type\n            ], [[MODEL, /^/, 'Chromecast '], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /fuchsia.*crkey/i                                                   // Google Chromecast Nest Hub\n            ], [[MODEL, CHROMECAST+' Nest Hub'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /crkey/i                                                            // Google Chromecast, Linux-based or unknown\n            ], [[MODEL, CHROMECAST], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /(portaltv)/i                                                       // Facebook Portal TV\n            ], [MODEL, [VENDOR, FACEBOOK], [TYPE, SMARTTV]], [\n            /droid.+aft(\\w+)( bui|\\))/i                                         // Fire TV\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [\n            /(shield \\w+ tv)/i                                                  // Nvidia Shield TV\n            ], [MODEL, [VENDOR, NVIDIA], [TYPE, SMARTTV]], [\n            /\\(dtv[\\);].+(aquos)/i,\n            /(aquos-tv[\\w ]+)\\)/i                                               // Sharp\n            ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[\n            /(bravia[\\w ]+)( bui|\\))/i                                          // Sony\n            ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [\n            /(mi(tv|box)-?\\w+) bui/i                                            // Xiaomi\n            ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [\n            /Hbbtv.*(technisat) (.*);/i                                         // TechniSAT\n            ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n            /\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i,                          // Roku\n            /hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i         // HbbTV devices\n            ], [[VENDOR, /.+\\/(\\w+)/, '$1', strMapper, {'LG':'lge'}], [MODEL, trim], [TYPE, SMARTTV]], [\n\n            ///////////////////\n            // CONSOLES\n            ///////////////////\n\n            /(playstation \\w+)/i                                                // Playstation\n            ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [\n            /\\b(xbox(?: one)?(?!; xbox))[\\); ]/i                                // Microsoft Xbox\n            ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [\n            /(ouya)/i,                                                          // Ouya\n            /(nintendo) (\\w+)/i,                                                // Nintendo\n            /(retroid) (pocket ([^\\)]+))/i,                                     // Retroid Pocket\n            /(valve).+(steam deck)/i,\n            /droid.+; ((shield|rgcube|gr0006))( bui|\\))/i                       // Nvidia Portable/Anbernic/Logitech\n            ], [[VENDOR, strMapper, { 'Nvidia': 'Shield', 'Anbernic': 'RGCUBE', 'Logitech': 'GR0006' }], MODEL, [TYPE, CONSOLE]], [\n\n            ///////////////////\n            // WEARABLES\n            ///////////////////\n\n            /\\b(sm-[lr]\\d\\d[0156][fnuw]?s?|gear live)\\b/i                       // Samsung Galaxy Watch\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, WEARABLE]], [\n            /((pebble))app/i,                                                   // Pebble\n            /(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\\w ]*)( bui|\\))/i // Asus ZenWatch / LG Watch / Pixel Watch / Xiaomi Watch\n            ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n            /(ow(?:19|20)?we?[1-3]{1,3})/i                                      // Oppo Watch\n            ], [MODEL, [VENDOR, OPPO], [TYPE, WEARABLE]], [\n            /(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i                              // Apple Watch\n            ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [\n            /(opwwe\\d{3})/i                                                     // OnePlus Watch\n            ], [MODEL, [VENDOR, ONEPLUS], [TYPE, WEARABLE]], [\n            /(moto 360)/i                                                       // Motorola 360\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, WEARABLE]], [\n            /(smartwatch 3)/i                                                   // Sony SmartWatch\n            ], [MODEL, [VENDOR, SONY], [TYPE, WEARABLE]], [\n            /(g watch r)/i                                                      // LG G Watch R\n            ], [MODEL, [VENDOR, LG], [TYPE, WEARABLE]], [\n            /droid.+; (wt63?0{2,3})\\)/i\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [\n\n            ///////////////////\n            // XR\n            ///////////////////\n\n            /droid.+; (glass) \\d/i                                              // Google Glass\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, XR]], [\n            /(pico) ([\\w ]+) os\\d/i                                             // Pico\n            ], [VENDOR, MODEL, [TYPE, XR]], [\n            /(quest( \\d| pro)?s?).+vr/i                                         // Meta Quest\n            ], [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]], [\n            /mobile vr; rv.+firefox/i                                           // Unidentifiable VR device using Firefox Reality / Wolvic\n            ], [[TYPE, XR]], [\n\n            ///////////////////\n            // EMBEDDED\n            ///////////////////\n\n            /(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i                              // Tesla\n            ], [VENDOR, [TYPE, EMBEDDED]], [\n            /(aeobc)\\b/i                                                        // Echo Dot\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [\n            /(homepod).+mac os/i                                                // Apple HomePod\n            ], [MODEL, [VENDOR, APPLE], [TYPE, EMBEDDED]], [\n            /windows iot/i                                                      // Unidentifiable embedded device using Windows IoT\n            ], [[TYPE, EMBEDDED]], [\n\n            ////////////////////\n            // MIXED (GENERIC)\n            ///////////////////\n\n            /droid.+; ([\\w- ]+) (4k|android|smart|google)[- ]?tv/i              // Unidentifiable SmartTV\n            ], [MODEL, [TYPE, SMARTTV]], [\n            /\\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\\w ]+safari)\\b/i\n            ], [[TYPE, SMARTTV]], [\n            /droid .+?; ([^;]+?)(?: bui|; wv\\)|\\) applew|; hmsc).+?(mobile|vr|\\d) safari/i\n            ], [MODEL, [TYPE, strMapper, { 'mobile' : 'Mobile', 'xr' : 'VR', '*' : TABLET }]], [\n            /\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i                      // Unidentifiable Tablet\n            ], [[TYPE, TABLET]], [\n            /(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i    // Unidentifiable Mobile\n            ], [[TYPE, MOBILE]], [\n            /droid .+?; ([\\w\\. -]+)( bui|\\))/i                                  // Generic Android Device\n            ], [MODEL, [VENDOR, 'Generic']]\n        ],\n\n        engine : [[\n\n            /windows.+ edge\\/([\\w\\.]+)/i                                       // EdgeHTML\n            ], [VERSION, [NAME, EDGE+'HTML']], [\n\n            /(arkweb)\\/([\\w\\.]+)/i                                              // ArkWeb\n            ], [NAME, VERSION], [\n\n            /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i                         // Blink\n            ], [VERSION, [NAME, 'Blink']], [\n\n            /(presto)\\/([\\w\\.]+)/i,                                             // Presto\n            /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo\n            /ekioh(flow)\\/([\\w\\.]+)/i,                                          // Flow\n            /(khtml|tasman|links|dillo)[\\/ ]\\(?([\\w\\.]+)/i,                     // KHTML/Tasman/Links/Dillo\n            /(icab)[\\/ ]([23]\\.[\\d\\.]+)/i,                                      // iCab\n\n            /\\b(libweb)/i                                                       // LibWeb\n            ], [NAME, VERSION], [\n            /ladybird\\//i\n            ], [[NAME, 'LibWeb']], [\n\n            /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i                                     // Gecko\n            ], [VERSION, NAME]\n        ],\n\n        os : [[\n\n            // Windows\n            /(windows nt) (6\\.[23]); arm/i                                      // Windows RT\n            ], [[NAME, /N/, 'R'], [VERSION, strMapper, windowsVersionMap]], [\n            /(windows (?:phone|mobile|iot))(?: os)?[\\/ ]?([\\d\\.]*( se)?)/i,     // Windows IoT/Mobile/Phone\n                                                                                // Windows NT/3.1/95/98/ME/2000/XP/Vista/7/8/8.1/10/11\n            /(windows)[\\/ ](1[01]|2000|3\\.1|7|8(\\.1)?|9[58]|me|server 20\\d\\d( r2)?|vista|xp)/i\n            ], [NAME, VERSION], [\n            /windows nt ?([\\d\\.\\)]*)(?!.+xbox)/i,\n            /\\bwin(?=3| ?9|n)(?:nt| 9x )?([\\d\\.;]*)/i\n            ], [[VERSION, /(;|\\))/g, '', strMapper, windowsVersionMap], [NAME, WINDOWS]], [\n            /(windows ce)\\/?([\\d\\.]*)/i                                         // Windows CE\n            ], [NAME, VERSION], [\n\n            // iOS/macOS\n            /[adehimnop]{4,7}\\b(?:.*os ([\\w]+) like mac|; opera)/i,             // iOS\n            /(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\\/ ]([\\w\\.]+)/i,\n            /\\btvos ?([\\w\\.]+)/i,\n            /cfnetwork\\/.+darwin/i\n            ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n            /(mac os x) ?([\\w\\. ]*)/i,\n            /(macintosh|mac_powerpc\\b)(?!.+(haiku|morphos))/i                   // Mac OS\n            ], [[NAME, 'macOS'], [VERSION, /_/g, '.']], [\n\n            // Google Chromecast\n            /android ([\\d\\.]+).*crkey/i                                         // Google Chromecast, Android-based\n            ], [VERSION, [NAME, CHROMECAST + ' Android']], [\n            /fuchsia.*crkey\\/([\\d\\.]+)/i                                        // Google Chromecast, Fuchsia-based\n            ], [VERSION, [NAME, CHROMECAST + ' Fuchsia']], [\n            /crkey\\/([\\d\\.]+).*devicetype\\/smartspeaker/i                       // Google Chromecast, Linux-based Smart Speaker\n            ], [VERSION, [NAME, CHROMECAST + ' SmartSpeaker']], [\n            /linux.*crkey\\/([\\d\\.]+)/i                                          // Google Chromecast, Legacy Linux-based\n            ], [VERSION, [NAME, CHROMECAST + ' Linux']], [\n            /crkey\\/([\\d\\.]+)/i                                                 // Google Chromecast, unknown\n            ], [VERSION, [NAME, CHROMECAST]], [\n\n            // Mobile OSes\n            /droid ([\\w\\.]+)\\b.+(android[- ]x86)/i                              // Android-x86\n            ], [VERSION, NAME], [                                               \n            /(ubuntu) ([\\w\\.]+) like android/i                                  // Ubuntu Touch\n            ], [[NAME, /(.+)/, '$1 Touch'], VERSION], [\n            /(harmonyos)[\\/ ]?([\\d\\.]*)/i,                                      // HarmonyOS\n                                                                                // Android/Blackberry/WebOS/QNX/Bada/RIM/KaiOS/Maemo/MeeGo/S40/Sailfish OS/OpenHarmony/Tizen\n            /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\\w*[-\\/\\.; ]?([\\d\\.]*)/i\n            ], [NAME, VERSION], [\n            /\\(bb(10);/i                                                        // BlackBerry 10\n            ], [VERSION, [NAME, BLACKBERRY]], [\n            /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\\/ ]?([\\w\\.]*)/i       // Symbian\n            ], [VERSION, [NAME, 'Symbian']], [\n            /mozilla\\/[\\d\\.]+ \\((?:mobile[;\\w ]*|tablet|tv|[^\\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\\w\\.]+)\\).+gecko\\//i // Firefox OS\n            ], [VERSION, [NAME, FIREFOX+' OS']], [\n            /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i,                             // WebOS\n            /webos(?:[ \\/]?|\\.tv-20(?=2[2-9]))(\\d[\\d\\.]*)/i\n            ], [VERSION, [NAME, 'webOS']], [\n            /web0s;.+?(?:chr[o0]me|safari)\\/(\\d+)/i\n                                                                                // https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine\n            ], [[VERSION, strMapper, {'25':'120','24':'108','23':'94','22':'87','6':'79','5':'68','4':'53','3':'38','2':'538','1':'537','*':'TV'}], [NAME, 'webOS']], [                   \n            /watch(?: ?os[,\\/ ]|\\d,\\d\\/)([\\d\\.]+)/i                              // watchOS\n            ], [VERSION, [NAME, 'watchOS']], [\n\n            // Google ChromeOS\n            /cros [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i                                    // Chromium OS\n            ], [VERSION, [NAME, 'Chrome OS']],[\n\n            // Smart TVs\n            /kepler ([\\w\\.]+); (aft|aeo)/i                                      // Vega OS\n            ], [VERSION, [NAME, 'Vega OS']],[\n            /(netrange)mmh/i,                                                   // Netrange\n            /(nettv)\\/(\\d+\\.[\\w\\.]+)/i,                                         // NetTV\n\n            // Console\n            /(nintendo|playstation) (\\w+)/i,                                    // Nintendo/Playstation\n            /(xbox); +xbox ([^\\);]+)/i,                                         // Microsoft Xbox (360, One, X, S, Series X, Series S)\n            /(pico) .+os([\\w\\.]+)/i,                                            // Pico\n\n            // Other\n            /\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i,                            // Joli/Palm\n            /linux.+(mint)[\\/\\(\\) ]?([\\w\\.]*)/i,                                // Mint\n            /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\\d\\.]*)/i,  // Mageia/VectorLinux/Fuchsia/ArcaOS/Arch\n            /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\\/ ]?(?!chrom|package)([-\\w\\.]*)/i,\n                                                                                // Ubuntu/Debian/SUSE/Gentoo/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire/Knoppix\n            /((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i,                              // Solaris\n            /\\b(aix)[; ]([1-9\\.]{0,4})/i,                                       // AIX\n            /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\\w*| ?)([\\w\\.]*)/i,         // Hurd/Linux/MorphOS\n            /(gnu) ?([\\w\\.]*)/i,                                                // GNU\n            /\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly\n            /(haiku) ?(r\\d)?/i                                                  // Haiku\n            ], [NAME, VERSION], [\n            /(sunos) ?([\\d\\.]*)/i                                               // Solaris\n            ], [[NAME, 'Solaris'], VERSION], [\n            /\\b(beos|os\\/2|amigaos|openvms|hp-ux|serenityos)/i,                 // BeOS/OS2/AmigaOS/OpenVMS/HP-UX/SerenityOS\n            /(unix) ?([\\w\\.]*)/i                                                // UNIX\n            ], [NAME, VERSION]\n        ]\n    };\n\n    /////////////////\n    // Factories\n    ////////////////\n\n    var defaultProps = (function () {\n            var props = { init : {}, isIgnore : {}, isIgnoreRgx : {}, toString : {}};\n            setProps.call(props.init, [\n                [BROWSER, [NAME, VERSION, MAJOR, TYPE]],\n                [CPU, [ARCHITECTURE]],\n                [DEVICE, [TYPE, MODEL, VENDOR]],\n                [ENGINE, [NAME, VERSION]],\n                [OS, [NAME, VERSION]]\n            ]);\n            setProps.call(props.isIgnore, [\n                [BROWSER, [VERSION, MAJOR]],\n                [ENGINE, [VERSION]],\n                [OS, [VERSION]]\n            ]);\n            setProps.call(props.isIgnoreRgx, [\n                [BROWSER, / ?browser$/i],\n                [OS, / ?os$/i]\n            ]);\n            setProps.call(props.toString, [\n                [BROWSER, [NAME, VERSION]],\n                [CPU, [ARCHITECTURE]],\n                [DEVICE, [VENDOR, MODEL]],\n                [ENGINE, [NAME, VERSION]],\n                [OS, [NAME, VERSION]]\n            ]);\n            return props;\n    })();\n\n    var createIData = function (item, itemType) {\n\n        var init_props = defaultProps.init[itemType],\n            is_ignoreProps = defaultProps.isIgnore[itemType] || 0,\n            is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0,\n            toString_props = defaultProps.toString[itemType] || 0;\n\n        function IData () {\n            setProps.call(this, init_props);\n        }\n\n        IData.prototype.getItem = function () {\n            return item;\n        };\n\n        IData.prototype.withClientHints = function () {\n\n            // nodejs / non-client-hints browsers\n            if (!NAVIGATOR_UADATA) {\n                return item\n                        .parseCH()\n                        .get();\n            }\n\n            // browsers based on chromium 85+\n            return NAVIGATOR_UADATA\n                    .getHighEntropyValues(CH_ALL_VALUES)\n                    .then(function (res) {\n                        return item\n                                .setCH(new UACHData(res, false))\n                                .parseCH()\n                                .get();\n            });\n        };\n\n        IData.prototype.withFeatureCheck = function () {\n            return item.detectFeature().get();\n        };\n\n        if (itemType != RESULT) {\n            IData.prototype.is = function (strToCheck) {\n                var is = false;\n                for (var i in this) {\n                    if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {\n                        is = true;\n                        if (strToCheck != TYPEOF.UNDEFINED) break;\n                    } else if (strToCheck == TYPEOF.UNDEFINED && is) {\n                        is = !is;\n                        break;\n                    }\n                }\n                return is;\n            };\n            IData.prototype.toString = function () {\n                var str = EMPTY;\n                for (var i in toString_props) {\n                    if (typeof(this[toString_props[i]]) !== TYPEOF.UNDEFINED) {\n                        str += (str ? ' ' : EMPTY) + this[toString_props[i]];\n                    }\n                }\n                return str || TYPEOF.UNDEFINED;\n            };\n        }\n\n        IData.prototype.then = function (cb) { \n            var that = this;\n            var IDataResolve = function () {\n                for (var prop in that) {\n                    if (that.hasOwnProperty(prop)) {\n                        this[prop] = that[prop];\n                    }\n                }\n            };\n            IDataResolve.prototype = {\n                is : IData.prototype.is,\n                toString : IData.prototype.toString,\n                withClientHints : IData.prototype.withClientHints,\n                withFeatureCheck : IData.prototype.withFeatureCheck\n            };\n            var resolveData = new IDataResolve();\n            cb(resolveData);\n            return resolveData;\n        };\n\n        return new IData();\n    };\n\n    /////////////////\n    // Constructor\n    ////////////////\n\n    function UACHData (uach, isHttpUACH) {\n        uach = uach || {};\n        setProps.call(this, CH_ALL_VALUES);\n        if (isHttpUACH) {\n            setProps.call(this, [\n                [BRANDS, itemListToArray(uach[CH])],\n                [FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],\n                [MOBILE, /\\?1/.test(uach[CH_MOBILE])],\n                [MODEL, stripQuotes(uach[CH_MODEL])],\n                [PLATFORM, stripQuotes(uach[CH_PLATFORM])],\n                [PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],\n                [ARCHITECTURE, stripQuotes(uach[CH_ARCH])],\n                [FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],\n                [BITNESS, stripQuotes(uach[CH_BITNESS])]\n            ]);\n        } else {\n            for (var prop in uach) {\n                if(this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];\n            }\n        }\n    }\n\n    function UAItem (itemType, ua, rgxMap, uaCH) {\n        setProps.call(this, [\n            ['itemType', itemType],\n            ['ua', ua],\n            ['uaCH', uaCH],\n            ['rgxMap', rgxMap],\n            ['data', createIData(this, itemType)]\n        ]);\n        return this;\n    }\n\n    UAItem.prototype.get = function (prop) {\n        if (!prop) return this.data;\n        return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;\n    };\n\n    UAItem.prototype.set = function (prop, val) {\n        this.data[prop] = val;\n        return this;\n    };\n\n    UAItem.prototype.setCH = function (ch) {\n        this.uaCH = ch;\n        return this;\n    };\n\n    UAItem.prototype.detectFeature = function () {\n        if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {\n            switch (this.itemType) {\n                case BROWSER:\n                    // Brave-specific detection\n                    if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {\n                        this.set(NAME, 'Brave');\n                    }\n                    break;\n                case DEVICE:\n                    // Chrome-specific detection: check for 'mobile' value of navigator.userAgentData\n                    if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {\n                        this.set(TYPE, MOBILE);\n                    }\n                    // iPadOS-specific detection: identified as Mac, but has some iOS-only properties\n                    if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {\n                        this.set(MODEL, 'iPad')\n                            .set(TYPE, TABLET);\n                    }\n                    break;\n                case OS:\n                    // Chrome-specific detection: check for 'platform' value of navigator.userAgentData\n                    if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {\n                        this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);\n                    }\n                    break;\n                case RESULT:\n                    var data = this.data;\n                    var detect = function (itemType) {\n                        return data[itemType]\n                                .getItem()\n                                .detectFeature()\n                                .get();\n                    };\n                    this.set(BROWSER, detect(BROWSER))\n                        .set(CPU, detect(CPU))\n                        .set(DEVICE, detect(DEVICE))\n                        .set(ENGINE, detect(ENGINE))\n                        .set(OS, detect(OS));\n            }\n        }\n        return this;\n    };\n\n    UAItem.prototype.parseUA = function () {\n        if (this.itemType != RESULT) {\n            rgxMapper.call(this.data, this.ua, this.rgxMap);\n        }\n        switch (this.itemType) {\n            case BROWSER:\n                this.set(MAJOR, majorize(this.get(VERSION)));\n                break;\n            case OS:\n                if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {\n                    // Based on the assumption that iOS version is tightly coupled with Safari version\n                    var realVersion = /\\) Version\\/([\\d\\.]+)/.exec(this.ua); // Get Safari version\n                    if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {\n                        this.set(VERSION, realVersion[1]);  // Set as iOS version\n                    }\n                }\n                break;\n        }\n        return this;\n    };\n\n    UAItem.prototype.parseCH = function () {\n        var uaCH = this.uaCH,\n            rgxMap = this.rgxMap;\n\n        switch (this.itemType) {\n            case BROWSER:\n            case ENGINE:\n                var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;\n                if (brands) {\n                    for (var i=0; i<brands.length; i++) {\n                        var brandName = brands[i].brand || brands[i],\n                            brandVersion = brands[i].version;\n                        if (this.itemType == BROWSER && \n                            !/not.a.brand/i.test(brandName) && \n                            (!prevName || \n                                (/Chrom/.test(prevName) && brandName != CHROMIUM) || \n                                (prevName == EDGE && /WebView2/.test(brandName))\n                            )) {\n                                brandName = strMapper(brandName, browserHintsMap);\n                                prevName = this.get(NAME);\n                                if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {\n                                    this.set(NAME, brandName)\n                                        .set(VERSION, brandVersion)\n                                        .set(MAJOR, majorize(brandVersion));\n                                }\n                                prevName = brandName;\n                        }\n                        if (this.itemType == ENGINE && brandName == CHROMIUM) {\n                            this.set(VERSION, brandVersion);\n                        }\n                    }\n                }\n                break;\n            case CPU:\n                var archName = uaCH[ARCHITECTURE];\n                if (archName) {\n                    if (archName && uaCH[BITNESS] == '64') archName += '64';\n                    rgxMapper.call(this.data, archName + ';', rgxMap);\n                }\n                break;\n            case DEVICE:\n                if (uaCH[MOBILE]) {\n                    this.set(TYPE, MOBILE);\n                }\n                if (uaCH[MODEL]) {\n                    this.set(MODEL, uaCH[MODEL]);\n                    if (!this.get(TYPE) || !this.get(VENDOR)) {\n                        var reParse = {};\n                        rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);\n                        if (!this.get(TYPE) && !!reParse.type) {\n                            this.set(TYPE, reParse.type);\n                        }\n                        if (!this.get(VENDOR) && !!reParse.vendor) {\n                            this.set(VENDOR, reParse.vendor);\n                        }\n                    }\n                }\n                if (uaCH[FORMFACTORS]) {\n                    var ff;\n                    if (typeof uaCH[FORMFACTORS] !== 'string') {\n                        var idx = 0;\n                        while (!ff && idx < uaCH[FORMFACTORS].length) {\n                            ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);\n                        }\n                    } else {\n                        ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);\n                    }\n                    this.set(TYPE, ff);\n                }\n                break;\n            case OS:\n                var osName = uaCH[PLATFORM];\n                if(osName) {\n                    var osVersion = uaCH[PLATFORMVER];\n                    if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');\n                    this.set(NAME, osName)\n                        .set(VERSION, osVersion);\n                }\n                // Xbox-Specific Detection\n                if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {\n                    this.set(NAME, 'Xbox')\n                        .set(VERSION, undefined);\n                }           \n                break;\n            case RESULT:\n                var data = this.data;\n                var parse = function (itemType) {\n                    return data[itemType]\n                            .getItem()\n                            .setCH(uaCH)\n                            .parseCH()\n                            .get();\n                };\n                this.set(BROWSER, parse(BROWSER))\n                    .set(CPU, parse(CPU))\n                    .set(DEVICE, parse(DEVICE))\n                    .set(ENGINE, parse(ENGINE))\n                    .set(OS, parse(OS));\n        }\n        return this;\n    };\n\n    function UAParser (ua, extensions, headers) {\n\n        if (typeof ua === TYPEOF.OBJECT) {\n            if (isExtensions(ua, true)) {\n                if (typeof extensions === TYPEOF.OBJECT) {\n                    headers = extensions;               // case UAParser(extensions, headers)           \n                }\n                extensions = ua;                        // case UAParser(extensions)\n            } else {\n                headers = ua;                           // case UAParser(headers)\n                extensions = undefined;\n            }\n            ua = undefined;\n        } else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {\n            headers = extensions;                       // case UAParser(ua, headers)\n            extensions = undefined;\n        }\n\n        if (headers) {\n            if (typeof headers.append === TYPEOF.FUNCTION) {\n                // Convert Headers object into a plain object\n                var kv = {};\n                headers.forEach(function (v, k) { kv[String(k).toLowerCase()] = v; });\n                headers = kv;\n            } else {\n                // Normalize headers field name into lowercase\n                var normalized = {};\n                for (var header in headers) {\n                    if (headers.hasOwnProperty(header)) {\n                        normalized[String(header).toLowerCase()] = headers[header];\n                    }\n                }\n                headers = normalized;\n            }\n        }\n        \n        if (!(this instanceof UAParser)) {\n            return new UAParser(ua, extensions, headers).getResult();\n        }\n\n        var userAgent = typeof ua === TYPEOF.STRING ? ua :                                       // Passed user-agent string\n                                (headers && headers[USER_AGENT] ? headers[USER_AGENT] :     // User-Agent from passed headers\n                                ((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent\n                                    EMPTY)),                                                // empty string\n\n            httpUACH = new UACHData(headers, true),\n            regexMap = extensions ? \n                        extend(defaultRegexes, extensions) : \n                        defaultRegexes,\n\n            createItemFunc = function (itemType) {\n                if (itemType == RESULT) {\n                    return function () {\n                        return new UAItem(itemType, userAgent, regexMap, httpUACH)\n                                    .set('ua', userAgent)\n                                    .set(BROWSER, this.getBrowser())\n                                    .set(CPU, this.getCPU())\n                                    .set(DEVICE, this.getDevice())\n                                    .set(ENGINE, this.getEngine())\n                                    .set(OS, this.getOS())\n                                    .get();\n                    };\n                } else {\n                    return function () {\n                        return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)\n                                    .parseUA()\n                                    .get();\n                    };\n                }\n            };\n            \n        // public methods\n        setProps.call(this, [\n            ['getBrowser', createItemFunc(BROWSER)],\n            ['getCPU', createItemFunc(CPU)],\n            ['getDevice', createItemFunc(DEVICE)],\n            ['getEngine', createItemFunc(ENGINE)],\n            ['getOS', createItemFunc(OS)],\n            ['getResult', createItemFunc(RESULT)],\n            ['getUA', function () { return userAgent; }],\n            ['setUA', function (ua) {\n                if (isString(ua)) userAgent = trim(ua, UA_MAX_LENGTH);\n                return this;\n            }]\n        ])\n        .setUA(userAgent);\n\n        return this;\n    }\n\n    UAParser.VERSION = LIBVERSION;\n    UAParser.BROWSER =  enumerize([NAME, VERSION, MAJOR, TYPE]);\n    UAParser.CPU = enumerize([ARCHITECTURE]);\n    UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);\n    UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);\n\n    export {UAParser};"
  },
  {
    "path": "test/data/ua/browser/browser-all.json",
    "content": "[\n    {\n        \"desc\"    : \"115 Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/24.3.0.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"115\",\n            \"version\" : \"24.3.0.3\",\n            \"major\"   : \"24\"\n        }\n    },\n    {\n        \"desc\"    : \"2345 Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; MI NOTE Pro Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36 Mb2345Browser/15.6.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"2345\",\n            \"version\" : \"15.6.2\",\n            \"major\"   : \"15\"\n        }\n    },\n    {\n        \"desc\"    : \"2345 Chrome\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML like Gecko) Chrome/39.0.2171.99 Safari/537.36 2345chrome v3.0.0.9739\",\n        \"expect\"  :\n        {\n            \"name\"    : \"2345\",\n            \"version\" : \"3.0.0.9739\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"2345 Explorer\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.90 Safari/537.36 2345Explorer/9.2.1.17116\",\n        \"expect\"  :\n        {\n            \"name\"    : \"2345\",\n            \"version\" : \"9.2.1.17116\",\n            \"major\"   : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"360 Browser on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_1 like Mac OS X) AppleWebKit/607.3.9 (KHTML, like Gecko) Mobile/16G102 QHBrowser/317 QihooBrowser/4.0.10\",\n        \"expect\"  :\n        {\n            \"name\"    : \"360\",\n            \"version\" : \"4.0.10\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"360 Secure Browser on Windows 10\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 QIHU 360SE\",\n        \"expect\"  :\n        {\n            \"name\"    : \"360\",\n            \"version\" : \"86.0.4240.198\",\n            \"major\"   : \"86\"\n        }\n    },\n    {\n        \"desc\"    : \"360 Speed Browser on Windows 10\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 QIHU 360EE\",\n        \"expect\"  :\n        {\n            \"name\"    : \"360\",\n            \"version\" : \"86.0.4240.198\",\n            \"major\"   : \"86\"\n        }\n    },\n    {\n        \"desc\"    : \"Alipay\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 10; zh-CN; V2034A Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 UWS/3.22.2.33 Mobile Safari/537.36 UCBS/3.22.2.33_211025173018 NebulaSDK/1.8.100112 Nebula AlipayDefined(nt:WIFI,ws:360|0|2.0) AliApp(AP/10.2.51.7100) AlipayClient/10.2.51.7100 Language/zh-Hans useStatusBar/true isConcaveScreen/true Region/CNAriver/1.0.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Alipay\",\n            \"version\" : \"10.2.51.7100\",\n            \"major\"   : \"10\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Alipay\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; VOG-AL00 Build/HUAWEIVOG-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.148 MYWeb/0.2.103.0_20230131112530 UWS/3.22.2.9999 UCBS/3.22.2.9999_220000000000 Mobile Safari/537.36 NebulaSDK/1.8.100112 Nebula AlipayDefined(nt:WIFI,ws:360|0|3.0) AliApp(AP/10.3.50.9999) AlipayClient/10.3.50.9999 Language/en isConcaveScreen/true Region/CN ProductType/devAriver/1.0.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Alipay\",\n            \"version\" : \"10.3.50.9999\",\n            \"major\"   : \"10\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Android Browser on Galaxy Nexus\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android Browser\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Android Browser on Galaxy S3\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 4.4.4; en-us; SAMSUNG GT-I9300I Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android Browser\",\n            \"version\" : \"1.5\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Android Browser on HTC Flyer (P510E)\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 3.2.1; ru-ru; HTC Flyer P510e Build/HTK75C) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android Browser\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Android Browser on Huawei Honor Glory II (U9508)\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 4.0.4; ru-by; HUAWEI U9508 Build/HuaweiU9508) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 ACHEETAHI/2100050044\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android Browser\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Android Browser on Huawei P8 (H891L)\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 4.4.4; HUAWEI H891L Build/HuaweiH891L) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android Browser\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Android Browser on Samsung S6 (SM-G925F)\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-G925F Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.0 Chrome/38.0.2125.102 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Samsung Internet\",\n            \"version\" : \"3.0\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Sailfish Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Sailfish 3.0; Mobile; rv:45.0) Gecko/45.0 Firefox/45.0 SailfishBrowser/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sailfish Browser\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Aloha\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU iPhone OS 19_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Version/19.0 Safari/605.1.15 AlohaBrowser/7.5.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Aloha\",\n            \"version\" : \"7.5.1\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Arora\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 5.1; de-CH) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Arora\",\n            \"version\" : \"0.2\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Atlas\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Atlas/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Atlas\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Avant\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB5; Avant Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Avant\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Avast Secure Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 Avast/72.0.1174.122\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Avast Secure Browser\",\n            \"version\" : \"72.0.1174.122\",\n            \"major\"   : \"72\"\n        }\n    },\n    {\n        \"desc\"    : \"AVG Secure Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 AVG/72.0.719.123\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AVG Secure Browser\",\n            \"version\" : \"72.0.719.123\",\n            \"major\"   : \"72\"\n        }\n    },\n    {\n        \"desc\"    : \"Avira Secure Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Avira/129.0.0.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Avira Secure Browser\",\n            \"version\" : \"129.0.0.0\",\n            \"major\"   : \"129\"\n        }\n    },\n    {\n        \"desc\"    : \"Baidu\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; baidubrowser 1.x)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"1.x\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Baidu\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 9; Redmi Note 5 Build/PKQ1.180904.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 bdbrowser/6.4.0.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"6.4.0.4\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Baidu\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.4.9999.1900 Safari/537.31 BDSpark/26.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"26.4\",\n            \"major\"   : \"26\"\n        }\n    },\n    {\n        \"desc\"    : \"Baidu\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) BaiduHD/5.4.0.0 Mobile/10A406 Safari/8536.25\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"5.4.0.0\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"BaiDu Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 BIDUBrowser/8.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"8.7\",\n            \"major\"   : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"baidu app on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16C101 main%2F1.0 baiduboxapp/11.12.0.18 (Baidu; P2 12.1.2)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"11.12.0.18\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"baidu app on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.1.0; BKK-AL10 Build/HONORBKK-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/11.11 baiduboxapp/11.11.0.0 (Baidu; P1 8.1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu\",\n            \"version\" : \"11.11.0.0\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"Bing\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/605.1.15 BingSapphire/31.8.430522001\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bing\",\n            \"version\" : \"31.8.430522001\",\n            \"major\"   : \"31\"\n        }\n    },\n    {\n        \"desc\"    : \"Bing\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 9; MIX 2 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4893.0 Mobile Safari/537.36 BingWeb/6.9.12\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bing\",\n            \"version\" : \"6.9.12\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Blazer\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Blazer\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Bolt\",\n        \"ua\"      : \"Mozilla/5.0 (X11; 78; CentOS; US-en) AppleWebKit/527+ (KHTML, like Gecko) Bolt/0.862 Version/3.0 Safari/523.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bolt\",\n            \"version\" : \"0.862\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Bowser\",\n        \"ua\"      : \"Mozilla/5.0 (iOS; like Mac OS X) AppleWebKit/536.36 (KHTML, like Gecko) not Chrome/27.0.1500.95 Mobile/10B141 Safari/537.36 Bowser/0.2.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bowser\",\n            \"version\" : \"0.2.1\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Camino\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en; rv:1.9.0.19) Gecko/2011091218 Camino/2.0.9 (like Firefox/3.0.19)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Camino\",\n            \"version\" : \"2.0.9\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Camino on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Camino\",\n            \"version\" : \"2.2.1\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Chimera\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; pl-PL; rv:1.0.1) Gecko/20021111 Chimera/0.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chimera\",\n            \"version\" : \"0.6\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome\",\n            \"version\" : \"20.0.1090.0\",\n            \"major\"   : \"20\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4758.102 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome\",\n            \"version\" : \"100.0.4758.102\",\n            \"major\"   : \"100\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome 112.0 on Win10\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome\",\n            \"version\" : \"112.0.0.0\",\n            \"major\"   : \"112\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome 112.0 on macOS\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome\",\n            \"version\" : \"112.0.0.0\",\n            \"major\"   : \"112\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome 111.0 on Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome\",\n            \"version\" : \"111.0.0.0\",\n            \"major\"   : \"111\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome 111.0 on ChromeOS\",\n        \"ua\"      : \"Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome\",\n            \"version\" : \"111.0.0.0\",\n            \"major\"   : \"111\"\n        }\n    },\n    {\n            \"desc\"    : \"Chrome Headless\",\n            \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome Safari/537.36\",\n            \"expect\"  :\n        {\n           \"name\"    : \"Chrome Headless\",\n           \"version\" : \"undefined\",\n           \"major\"   : \"undefined\"\n        }\n    },\n    {\n            \"desc\"    : \"Chrome Headless\",\n            \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/60.0.3112.113 Safari/537.36\",\n            \"expect\"  :\n        {\n           \"name\"    : \"Chrome Headless\",\n           \"version\" : \"60.0.3112.113\",\n           \"major\"   : \"60\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome WebView\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome WebView\",\n            \"version\" : \"43.0.2357.65\",\n            \"major\"   : \"43\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Chrome\",\n            \"version\" : \"19.0.1084.60\",\n            \"major\"   : \"19\"\n        }\n    },\n    {\n        \"desc\"    : \"Chromium\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Ubuntu/11.10 Chromium/16.0.912.21 Chrome/16.0.912.21 Safari/535.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chromium\",\n            \"version\" : \"16.0.912.21\",\n            \"major\"   : \"16\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Chrome\",\n            \"version\" : \"16.0.912.75\",\n            \"major\"   : \"16\"\n        }\n    },\n    {\n        \"desc\"    : \"Coc Coc Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) coc_coc_browser/78.0.129 Chrome/72.0.3626.129 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Coc Coc\",\n            \"version\" : \"78.0.129\",\n            \"major\"   : \"78\"\n        }\n    },\n    {\n        \"desc\"    : \"Comodo Dragon\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dragon\",\n            \"version\" : \"16.1.1.0\",\n            \"major\"   : \"16\"\n        }\n    },\n    {\n        \"desc\"    : \"Comodo Dragon\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Dragon/98.0.4758.102 Chrome/98.0.4758.102 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dragon\",\n            \"version\" : \"98.0.4758.102\",\n            \"major\"   : \"98\"\n        }\n    },\n    {\n        \"desc\"    : \"Conkeror\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:6.0.1) Gecko/20110831 conkeror/0.9.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"conkeror\",\n            \"version\" : \"0.9.3\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Dillo\",\n        \"ua\"      : \"Dillo/2.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dillo\",\n            \"version\" : \"2.2\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Dolphin\",\n        \"ua\"      : \"Mozilla/5.0 (SCH-F859/F859DG12;U;NUCLEUS/2.1;Profile/MIDP-2.1 Configuration/CLDC-1.1;480*800;CTC/2.0) Dolfin/2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dolphin\",\n            \"version\" : \"2.0\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Dooble\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Haiku BePC) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.17 Chrome/87.0.4280.144 Safari/537.36 Dooble/2023.12.25 Dooble/2023.12.25\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dooble\",\n            \"version\" : \"2023.12.25\",\n            \"major\"   : \"2023\"\n        }\n    },\n    {\n        \"desc\"    : \"Doris\",\n        \"ua\"      : \"Doris/1.15 [en] (Symbian)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Doris\",\n            \"version\" : \"1.15\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"DuckDuckGo\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.1517.4.1 Ddg/17.4.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DuckDuckGo\",\n            \"version\" : \"17.4.1\",\n            \"major\"   : \"17\"\n        }\n    },\n    {\n        \"desc\"    : \"DuckDuckGo\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.1.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile DuckDuckGo/5 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DuckDuckGo\",\n            \"version\" : \"5\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Ecosia on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; SM-G975U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36 (Ecosia android@85.0.4183.127)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ecosia\",\n            \"version\" : \"85.0.4183.127\",\n            \"major\"   : \"85\"\n        }\n    },\n    {\n        \"desc\"    : \"Ecosia on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60 (Ecosia ios@3.0.1.533)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ecosia\",\n            \"version\" : \"3.0.1.533\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Epiphany\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040628 Epiphany/1.2.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Epiphany\",\n            \"version\" : \"1.2.6\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Flow\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) EkiohFlow/5.7.4.30559 Flow/5.7.4 (like Gecko Firefox/53.0 rv:53.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Flow\",\n            \"version\" : \"5.7.4\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Go Browser\",\n        \"ua\"      : \"NokiaE66/GoBrowser/2.0.297\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoBrowser\",\n            \"version\" : \"2.0.297\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Waterfox\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.2.2 Waterfox/55.2.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Waterfox\",\n            \"version\" : \"55.2.2\",\n            \"major\"   : \"55\"\n        }\n    },\n    {\n        \"desc\"    : \"PaleMoon\",\n        \"ua\"      : \"(Windows NT 6.2; WOW64) KHTML/4.11 Gecko/20130308 Firefox/23.0 (PaleMoon/20.3)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PaleMoon\",\n            \"version\" : \"20.3\",\n            \"major\"   : \"20\"\n        }\n    },\n    {\n        \"desc\"    : \"PaleMoon\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:52.9) Gecko/20100101 Goanna/3.4 Firefox/52.9 PaleMoon/27.6.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PaleMoon\",\n            \"version\" : \"27.6.1\",\n            \"major\"   : \"27\"\n        }\n    },\n    {\n        \"desc\"    : \"Basilisk\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Goanna/4.0 Firefox/55.0 Basilisk/20171113\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Basilisk\",\n            \"version\" : \"20171113\",\n            \"major\"   : \"20171113\"\n        }\n    },\n    {\n        \"desc\"    : \"Facebook in-App Browser for Android with version\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/35.0.0.48.273;]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Facebook\",\n            \"version\" : \"35.0.0.48.273\",\n            \"major\"   : \"35\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Facebook in-App Browser for iOS with version\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304 [FBAN/FBIOS;FBAV/91.0.0.41.73;FBBV/57050710;FBDV/iPhone8,1;FBMD/iPhone;FBSN/iOS;FBSV/10.3.1;FBSS/2;FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBOP/5;FBRV/0])\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Facebook\",\n            \"version\" : \"91.0.0.41.73\",\n            \"major\"   : \"91\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Facebook in-App Browser for iOS without version\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone10,2;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Facebook\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Klarna in-App Browser for iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Klarna/23.36.223\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Klarna\",\n            \"version\" : \"23.36.223\",\n            \"major\"   : \"23\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Klarna in-App Browser for Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 12; moto g(60)s Build/S3RLS32.114-25-13; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 Klarna/23.36.215\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Klarna\",\n            \"version\" : \"23.36.215\",\n            \"major\"   : \"23\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Instagram in-App Browser for iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 142.0.0.22.109 (iPhone12,5; iOS 14_1; en_US; en-US; scale=3.00; 1242x2688; 214888322) NW/1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Instagram\",\n            \"version\" : \"142.0.0.22.109\",\n            \"major\"   : \"142\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Falkon\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Falkon/3.0.0 Chrome/61.0.3163.140 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Falkon\",\n            \"version\" : \"3.0.0\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Firebird\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007 Firebird/0.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firebird\",\n            \"version\" : \"0.7\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox\",\n            \"version\" : \"15.0a2\",\n            \"major\"   : \"15\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox\",\n            \"version\" : \"100.0\",\n            \"major\"   : \"100\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox Reality\",\n        \"ua\"      : \"Mozilla/5.0 (Android 7.1.2; Mobile VR; rv:65.0) Gecko/65.0 Firefox/65.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox Reality\",\n            \"version\" : \"65.0\",\n            \"major\"   : \"65\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox-based browser\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0 AppName/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox\",\n            \"version\" : \"80.0\",\n            \"major\"   : \"80\"\n        }\n    },\n    {\n        \"desc\"    : \"Fennec\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fennec\",\n            \"version\" : \"1.0a1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox for Maemo (Nokia N900)\",\n        \"ua\"      : \"Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fennec\",\n            \"version\" : \"10.0.1\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\": \"Firefox Focus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Focus/6.1.1 Chrome/68.0.3440.91 Mobile Safari/537.36\",\n        \"expect\": {\n            \"name\": \"Firefox Focus\",\n            \"version\": \"6.1.1\",\n            \"major\": \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Flock\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008100716 Firefox/3.0.3 Flock/2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Flock\",\n            \"version\" : \"2.0\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"GoBrowser\",\n        \"ua\"      : \"Nokia5700XpressMusic/GoBrowser/1.6.91\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoBrowser\",\n            \"version\" : \"1.6.91\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Helio\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 Helio/0.98.20\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Helio\",\n            \"version\" : \"0.98.20\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"HeyTap\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Safari/537.36 HeyTapBrowser/40.8.10.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HeyTap\",\n            \"version\" : \"40.8.10.1\",\n            \"major\"   : \"40\"\n        }\n    },\n    {\n        \"desc\"    : \"Hi Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 14; en; TECNO BG6m Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 HiBrowser/v2.25.6.3;lang=es;nation=DO;locale=es_DO UWS/ Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HiBrowser\",\n            \"version\" : \"2.25.6.3\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"HuaweiBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00；HMSCore/4.0.0 GMS/10.4 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Huawei Browser\",\n            \"version\" : \"10.0.3.102\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"HuaweiBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00；HMSCore/4.0.0 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Huawei Browser\",\n            \"version\" : \"10.0.3.102\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"HuaweiBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00；GMS/10.4 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Huawei Browser\",\n            \"version\" : \"10.0.3.102\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"HuaweiBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Huawei Browser\",\n            \"version\" : \"10.0.3.102\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"IceApe\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.19) Gecko/20110817 Iceape/2.0.14\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iceape\",\n            \"version\" : \"2.0.14\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"ICEBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Java 1.6.0_01; Windows XP 5.1 x86; en) ICEbrowser/v6_1_2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ICEbrowser\",\n            \"version\" : \"6.1.2\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"IceCat\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092921 IceCat/3.0.3-g1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"IceCat\",\n            \"version\" : \"3.0.3-g1\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Iceweasel\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.16) Gecko/2009121610 Iceweasel/3.0.6 (Debian-3.0.6-3)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iceweasel\",\n            \"version\" : \"3.0.6\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"iCab\",\n        \"ua\"      : \"iCab/2.9.5 (Macintosh; U; PPC; Mac OS X)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iCab\",\n            \"version\" : \"2.9.5\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"IEMobile\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) 320x240; VZW; Motorola-Q9c; Windows Mobile 6.1 Standard\",\n        \"expect\"  :\n        {\n            \"name\"    : \"IEMobile\",\n            \"version\" : \"7.11\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"IE 11 with IE token\",\n        \"ua\"      : \"Mozilla/5.0 (IE 11.0; Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko\",\n        \"expect\"  :\n        {\n            \"name\"    : \"IE\",\n            \"version\" : \"11.0\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"IE 11 without IE token\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko\",\n        \"expect\"  :\n        {\n            \"name\"    : \"IE\",\n            \"version\" : \"11.0\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"Iron\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1250.0 Iron/22.0.2150.0 Safari/537.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iron\",\n            \"version\" : \"22.0.2150.0\",\n            \"major\"   : \"22\"\n        }\n    },\n    {\n        \"desc\"    : \"Iron\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Iron Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iron\",\n            \"version\" : \"129.0.0.0\",\n            \"major\"   : \"129\"\n        }\n    },\n    {\n        \"desc\"    : \"Iron\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 11; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Mobile Iron Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iron\",\n            \"version\" : \"113.0.0.0\",\n            \"major\"   : \"113\"\n        }\n    },\n    {\n        \"desc\"    : \"Jasmine\",\n        \"ua\"      : \"SAMSUNG-S8000/S8000XXIF3 SHP/VPP/R5 Jasmine/1.0 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Jasmine\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"K-Meleon\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"K-Meleon\",\n            \"version\" : \"0.8.2\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Kindle Browser\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.5 (screen 600x800; rotate)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Kindle\",\n            \"version\" : \"2.5\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Klar < 4.1\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Klar/1.0 Chrome/58.0.3029.83 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Klar\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Konqueror\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Konqueror/3.5; Linux; X11; x86_64) KHTML/3.5.6 (like Gecko) (Kubuntu)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Konqueror\",\n            \"version\" : \"3.5\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Konqueror\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) konqueror/5.0.97 Safari/534.34\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Konqueror\",\n            \"version\" : \"5.0.97\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Lighthouse\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4590.2 Mobile Safari/537.36 Chrome-Lighthouse\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Lighthouse\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Luakit\",\n        \"ua\"      : \"Mozilla/5.0 (Linux x86_64) AppleWebKit/535.4+ (KHTML, like Gecko) WebKitGTK+/1.6.3 luakit\",\n        \"expect\"  :\n        {\n            \"name\"    : \"luakit\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Norton\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Norton/130.0.0.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Norton Private Browser\",\n            \"version\" : \"130.0.0.0\",\n            \"major\"   : \"130\"\n        }\n    },\n    {\n        \"desc\"    : \"Otter\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/602.1 (KHTML, like Gecko) Otter/1.0.81\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Otter\",\n            \"version\" : \"1.0.81\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"PicoBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; Pico Neo3 Link OS5.8.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Pico Browser\",\n            \"version\" : \"3.3.22\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"PicoBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.8.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.38 Chrome/105.0.5195.68 VR Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Pico Browser\",\n            \"version\" : \"3.3.38\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"PicoBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36 OculusBrowser/7.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Pico Browser\",\n            \"version\" : \"3.3.22\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Rekonq\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ) AppleWebKit/533.3 (KHTML, like Gecko) rekonq Safari/533.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"rekonq\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Smart Lenovo Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.10171 SLBChan/8\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Smart Lenovo Browser\",\n            \"version\" : \"8.0.0.10171\",\n            \"major\"   : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Smart Lenovo Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 SLBrowser/9.0.0.9011 SLBChan/10\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Smart Lenovo Browser\",\n            \"version\" : \"9.0.0.9011\",\n            \"major\"   : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"Surf Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Android 6.0; HUAWEI ALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36 SurfBrowser/3.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Surf\",\n            \"version\" : \"3.0\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"LG Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Unknown; Linux armv7l) AppleWebKit/537.1+ (KHTML, like Gecko) Safari/537.1+ LG Browser/6.00.00(+mouse+3D+SCREEN+TUNER; LGE; 47LA621V-ZD; 04.28.17; 0x00000001;); LG NetCast.TV-2013 /04.28.17 (LG, 47LA621V-ZD, wired)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LG Browser\",\n            \"version\" : \"6.00.00\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Ladybird\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; x86_64) Ladybird/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ladybird\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"LibreWolf\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0 LibreWolf/97.0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LibreWolf\",\n            \"version\" : \"97.0.1\",\n            \"major\"   : \"97\"\n        }\n    },\n    {\n        \"desc\"    : \"LINE on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.0; ASUS_Z00AD Build/LRX21V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36 Line/6.5.1/IAB\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Line\",\n            \"version\" : \"6.5.1\",\n            \"major\"   : \"6\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"LINE on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_6 like Mac OS X) AppleWebKit/604.5.6 (KHTML, like Gecko) Mobile/15D100 Safari Line/8.4.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Line\",\n            \"version\" : \"8.4.1\",\n            \"major\"   : \"8\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Lunascape\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090804 Firefox/3.5.2 Lunascape/5.1.4.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Lunascape\",\n            \"version\" : \"5.1.4.5\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Lynx\",\n        \"ua\"      : \"Lynx/2.8.5dev.16 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Lynx\",\n            \"version\" : \"2.8.5dev.16\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Maemo Browser\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux armv7l; ru-RU; rv:1.9.2.3pre) Gecko/20100723 Firefox/3.5 Maemo Browser 1.7.4.8 RX-51 N900\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maemo Browser\",\n            \"version\" : \"1.7.4.8\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.1.1; KFAUWI Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Safari/537.36 MxBrowser/4.3.5.2000\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"4.3.5.2000\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/10.0 Mobile/15E148 Safari/602.1 MXiOS/5.4.5.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"5.4.5.2\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux i686; Ubuntu 14.04.3 LTS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.0 Maxthon/1.0.5.3 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"1.0.5.3\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on macOS\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/604.5.6 (KHTML, like Gecko) Version/11.0.3 Safari/604.5.6 Maxthon/5.1.102\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"5.1.102\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on Windows Server 2003\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; .NET CLR 1.1.4322)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on Windows XP\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Maxthon on Windows 10\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 Maxthon/5.2.7.2000\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maxthon\",\n            \"version\" : \"5.2.7.2000\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Midori\",\n        \"ua\"      : \"Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Midori\",\n            \"version\" : \"0.2.2\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Minimo\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux armv6l; rv 1.8.1.5pre) Gecko/20070619 Minimo/0.020\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Minimo\",\n            \"version\" : \"0.020\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"MIUI Browser on Xiaomi Hongmi WCDMA (HM2013023)\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 4.2.2; ru-ru; 2013023 Build/HM2013023) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 XiaoMi/MiuiBrowser/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MIUI Browser\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Mobile Safari\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Safari\",\n            \"version\" : \"4.0.5\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Mobile Safari\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)  Mobile/15E148 Safari/604.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Safari\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Mosaic\",\n        \"ua\"      : \"NCSA_Mosaic/2.6 (X11; SunOS 4.1.3 sun4m)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mosaic\",\n            \"version\" : \"2.6\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Mozilla\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20070606\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mozilla\",\n            \"version\" : \"5.0\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Mozilla\",\n        \"ua\"      : \"Mozilla/2.02 [fr] (WinNT; I)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mozilla\",\n            \"version\" : \"2.02\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"MSIE\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"IE\",\n            \"version\" : \"5.0b1\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"NetFront\",\n        \"ua\"      : \"Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NetFront\",\n            \"version\" : \"3.0\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Netscape on Windows ME\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8.1.8pre) Gecko/20071015 Firefox/2.0.0.7 Navigator/9.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Netscape\",\n            \"version\" : \"9.0\",\n            \"major\"   : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"Netscape on Windows 2000\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20050519 Netscape/8.0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Netscape\",\n            \"version\" : \"8.0.1\",\n            \"major\"   : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Netscape 6\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win95; de-DE; rv:0.9.2) Gecko/20010726 Netscape6/6.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Netscape\",\n            \"version\" : \"6.1\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"NetSurf in Plan9\",\n        \"ua\"      : \"Mozilla/5.0 (Plan9) NetSurf/3.12\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NetSurf\",\n            \"version\" : \"3.12\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"NetSurf in Linux\",\n        \"ua\"      : \"NetSurf/3.10 (Linux; Arch Linux)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NetSurf\",\n            \"version\" : \"3.10\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/025.007; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.37 Mobile Safari/533.4 3gpp-gba\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NokiaBrowser\",\n            \"version\" : \"7.3.1.37\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Obigo\",\n        \"ua\"      : \"LG-GS290/V100 Obigo/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Obigo\",\n            \"version\" : \"WAP2.0\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Obigo\",\n        \"ua\"      : \"LG/KU990i/v10a Browser/Obigo-Q05A/3.6 MMS/LG-MMS-V1.0/1.2 Java/ASVM/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Obigo\",\n            \"version\" : \"Q05A\",\n            \"major\"   : \"05\"\n        }\n    },\n    {\n        \"desc\"    : \"Oculus Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; SM-G920I Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/3.4.9 SamsungBrowser/4.0 Chrome/57.0.2987.146 Mobile VR Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Oculus Browser\",\n            \"version\" : \"3.4.9\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Oculus Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; Quest 2) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/15.0.0.0.22.280317669 SamsungBrowser/4.0 Chrome/89.0.4389.90 VR Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Oculus Browser\",\n            \"version\" : \"15.0.0.0.22.280317669\",\n            \"major\"   : \"15\"\n        }\n    },\n    {\n        \"desc\"    : \"OmniWeb\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558.48\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OmniWeb\",\n            \"version\" : \"558.48\",\n            \"major\"   : \"558\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera > 9.80\",\n        \"ua\"      : \"Opera/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto/2.2.15 Version/10.10\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera\",\n            \"version\" : \"10.10\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera < 9.80 on Windows\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.01 [en]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera\",\n            \"version\" : \"6.01\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera < 9.80 on OSX\",\n        \"ua\"      : \"Opera/8.5 (Macintosh; PPC Mac OS X; U; en)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera\",\n            \"version\" : \"8.5\",\n            \"major\"   : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Mobile\",\n        \"ua\"      : \"Opera/9.80 (Android 2.3.5; Linux; Opera Mobi/ADR-1111101157; U; de) Presto/2.9.201 Version/11.50\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Mobi\",\n            \"version\" : \"11.50\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Webkit\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.123 Mobile Safari/537.22 OPR/14.0.1025.52315\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera\",\n            \"version\" : \"14.0.1025.52315\",\n            \"major\"   : \"14\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Mini\",\n        \"ua\"      : \"Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.21214/19.916; U; en) Presto/2.5.25\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Mini\",\n            \"version\" : \"5.1.21214\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Mini 8 above on iPhone\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) OPiOS/12.1.1.98980 Mobile/13C75 Safari/9537.53\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Mini\",\n            \"version\" : \"12.1.1.98980\",\n            \"major\"   : \"12\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera GX on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; Redmi Note 8 Pro Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.168 Mobile Safari/537.36 OPX/2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera GX\",\n            \"version\" : \"2\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera GX on Windows\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.50747 OPRGX/60.0.3255.50747\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera GX\",\n            \"version\" : \"60.0.3255.50747\",\n            \"major\"   : \"60\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Neon\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.21 Safari/537.36 MMS/1.0.2531.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Neon\",\n            \"version\" : \"1.0.2531.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Tablet\",\n        \"ua\"      : \"Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Tablet\",\n            \"version\" : \"11.1\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Coast\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X; en) AppleWebKit/601.1.46 (KHTML, like Gecko) Coast/5.04.110603 Mobile/13F69 Safari/7534.48.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Coast\",\n            \"version\" : \"5.04.110603\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Touch\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; Lenovo P2a42 Build/NRD90N) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36 OPT/1.10.33\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Opera Touch\",\n            \"version\" : \"1.10.33\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"OviBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Series40; NokiaX3-02/le6.32; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.0.0.11.8\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OviBrowser\",\n            \"version\" : \"1.0.0.11.8\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"PhantomJS\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.2 Safari/534.34\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PhantomJS\",\n            \"version\" : \"1.9.2\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Phoenix\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2b) Gecko/20021029 Phoenix/0.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Phoenix\",\n            \"version\" : \"0.4\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Polaris\",\n        \"ua\"      : \"LG-LX600 Polaris/6.0 MMP/2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Polaris\",\n            \"version\" : \"6.0\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"QQBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QQBrowser\",\n            \"version\" : \"7.1\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"QQBrowser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 9; zh-cn; vivo X21 Build/PKQ1.180819.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/9.9 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QQBrowser\",\n            \"version\" : \"9.9\",\n            \"major\"   : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"Quark\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 12; zh-Hans-CN; JLH-AN00 Build/HONORJLH-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.8.2.221 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Quark\",\n            \"version\" : \"5.8.2.221\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Quark\",\n        \"ua\"      : \"mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/112.0.0.0 safari/537.36 quarkpc/1.5.5.75\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Quark\",\n            \"version\" : \"1.5.5.75\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"QupZilla\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.9 Safari/538.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QupZilla\",\n            \"version\" : \"1.8.9\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"qutebrowser\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) qutebrowser/2.4.0 QtWebEngine/5.15.6 Chrome/95.0.4628.2 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"qutebrowser\",\n            \"version\" : \"2.4.0\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Qwant\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) QwantMobile/6.7.6 Mobile/15E148 Safari/605.1.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Qwant\",\n            \"version\" : \"6.7.6\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Qwant\",\n        \"ua\"      : \"QwantMobile/2.0 (Android 8.0.0; Mobile; rv:59.0) Gecko/59.0 Firefox/59.0 QwantBrowser/59.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Qwant\",\n            \"version\" : \"59.0\",\n            \"major\"   : \"59\"\n        }\n    },\n    {\n        \"desc\"    : \"Qwant\",\n        \"ua\"      : \"QwantMobile/2.0 (iPad; CPU OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) QwantiOS/2.7.0b1 Mobile/15E148 Safari/605.1.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Qwant\",\n            \"version\" : \"2.0\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Rekonq 2\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) rekonq/2.2.1 Safari/537.21\",\n        \"expect\"  :\n        {\n            \"name\"    : \"rekonq\",\n            \"version\" : \"2.2.1\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"RockMelt\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) RockMelt/0.8.36.78 Chrome/7.0.517.44 Safari/534.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"RockMelt\",\n            \"version\" : \"0.8.36.78\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Safari\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Safari\",\n            \"version\" : \"5.0.1\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Safari < 3.0\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/419 (KHTML, like Gecko) Safari/419.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Safari\",\n            \"version\" : \"1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Samsung Internet for Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG-SM-G925A Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Samsung Internet\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Samsung Internet for Tizen Mobile\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Tizen 2.3; SAMSUNG SM-Z130H) AppleWebKit/537.3 (KHTML, like Gecko) SamsungBrowser/1.0 Mobile Safari/537.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Samsung Internet\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Samsung Internet for Smart-TV\",\n        \"ua\"      : \"Mozilla/5.0 (SMART-TV; Linux; Tizen 2.3) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.0 TV Safari/538.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Samsung Internet\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Samsung Internet for Gear VR\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-G925K Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile VR Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Samsung Internet\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Samsung Internet in Redmi 8A\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; Redmi 8A) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Samsung Internet\",\n            \"version\" : \"23.0\",\n            \"major\"   : \"23\"\n        }\n    },\n    {\n        \"desc\"    : \"SeaMonkey\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b4pre) Gecko/20090405 SeaMonkey/2.0b1pre\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SeaMonkey\",\n            \"version\" : \"2.0b1pre\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"SeaMonkey on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SeaMonkey\",\n            \"version\" : \"2.7.1\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Silk Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-84)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Silk\",\n            \"version\" : \"1.1.0-84\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Skyfire\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17 Skyfire/2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Skyfire\",\n            \"version\" : \"2.0\",\n            \"major\"   : \"2\"\n        }\n    },    \n    {\n        \"desc\"    : \"Sleipnir\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; SOV37 Build/52.1.C.0.220; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.120 Mobile Safari/537.36 Sleipnir/3.7.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sleipnir\",\n            \"version\" : \"3.7.5\",\n            \"major\"   : \"3\"\n        }\n    },\n\n    {\n        \"desc\"    : \"Sleipnir\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Sleipnir 2.8.4)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sleipnir\",\n            \"version\" : \"2.8.4\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Sleipnir\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) Sleipnir/2.8.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sleipnir\",\n            \"version\" : \"2.8.4\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"SlimBoat\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.34 (KHTML, like Gecko) SlimBoat/1.1.23 Chrome/11.0.696.7 Version/5.1 Safari/534.34\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SlimBoat\",\n            \"version\" : \"1.1.23\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"SlimBrowser\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SlimBrowser)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SlimBrowser\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Slimjet\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36 Slimjet/20.0.2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Slimjet\",\n            \"version\" : \"20.0.2.0\",\n            \"major\"   : \"20\"\n        }\n    },\n    {\n        \"desc\"    : \"Steam Client\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; Valve Steam Client/default/1705108172) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Steam\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Steam Big Picture\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; X11; en-US; Valve Steam Tenfoot/1660688177; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Steam\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Steam Overlay\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam GameOverlay/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Steam\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Swiftfox\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Swiftfox\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Tesla\",\n        \"ua\"      : \"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/601.1 (KHTML, like Gecko) Tesla QtCarBrowser Safari/601.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tesla\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Tesla\",\n        \"ua\"      : \"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/2020.16.2.1-e99c70fff409\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tesla\",\n            \"version\" : \"2020.16.2.1-e99c70fff409\",\n            \"major\"   : \"2020\"\n        }\n    },\n    {\n        \"desc\"    : \"Tizen Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Tizen/1.0 like Android; en-us; AppleWebKit/534.46 (KHTML, like Gecko) Tizen Browser/1.0 Mobile\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tizen Browser\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser on Windows - Issue #811\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 UCPC/1.1.0.12\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"1.1.0.12\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 UBrowser/5.6.12860.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"5.6.12860.7\",\n            \"major\"   : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 6.0.1; en-US; Lenovo P2a42 Build/MMB29M) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/11.2.0.915 U3/0.8.0 Mobile Safari/534.30\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"11.2.0.915\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser on Samsung\",\n        \"ua\"      : \"Mozilla/5.0 (Java; U; Pt-br; samsung-gt-s5620) UCBrowser8.2.1.144/69/352/UCWEB Mobile UNTRUSTED/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"8.2.1.144\",\n            \"major\"   : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser on Nokia\",\n        \"ua\"      : \"Mozilla/5.0 (S60V3; U; en-in; NokiaN73)/UC Browser8.4.0.159/28/351/UCWEB Mobile\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"8.4.0.159\",\n            \"major\"   : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser J2ME\",\n        \"ua\"      : \"UCWEB/2.0 (MIDP-2.0; U; zh-CN; HTC EVO 3D X515m) U2/1.0.0 UCBrowser/10.4.0.558 U2/1.0.0 Mobile\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"10.4.0.558\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"UC Browser J2ME 2\",\n        \"ua\"      : \"JUC (Linux; U; 2.3.5; zh-cn; GT-I9100; 480*800) UCWEB7.9.0.94/139/800\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UCBrowser\",\n            \"version\" : \"7.9.0.94\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"UP.Browser\",\n        \"ua\"      : \"BenQ-CF61/1.00/WAP2.0/MIDP2.0/CLDC1.0 UP.Browser/6.3.0.4.c.1.102 (GUI) MMP/2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UP.Browser\",\n            \"version\" : \"6.3.0.4.c.1.102\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\": \"WeChat on iOS\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 MicroMessenger/6.3.6 NetType/WIFI Language/zh_CN\",\n        \"expect\":\n        {\n            \"name\": \"WeChat\",\n            \"version\": \"6.3.6\",\n            \"major\": \"6\"\n        }\n    },\n    {\n        \"desc\": \"WeChat on Android\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.1; zh-cn; Lenovo K50-t5 Build/LMY47D) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025478 Mobile Safari/533.1 MicroMessenger/6.3.5.50_r1573191.640 NetType/WIFI Language/zh_CN\",\n        \"expect\":\n        {\n            \"name\": \"WeChat\",\n            \"version\": \"6.3.5.50_r1573191.640\",\n            \"major\": \"6\"\n        }\n    },\n    {\n        \"desc\": \"WeiBo on Android\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16A366 Weibo (iPhone8,2__weibo__8.9.3__iphone__os12.0)\",\n        \"expect\":\n        {\n            \"name\": \"weibo\",\n            \"version\": \"8.9.3\",\n            \"major\": \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivaldi\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.83.38 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Vivaldi\",\n            \"version\" : \"1.0.83.38\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivaldi on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.88 Safari/537.36 Vivaldi/2.4.1488.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Vivaldi\",\n            \"version\" : \"2.4.1488.36\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivo Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 13; 23049RAD8C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 VivoBrowser/16.7.1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Vivo Browser\",\n            \"version\" : \"16.7.1.1\",\n            \"major\"   : \"16\"\n        }\n    },\n    {\n        \"desc\"    : \"w3m\",\n        \"ua\"      : \"w3m/0.5.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"w3m\",\n            \"version\" : \"0.5.1\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"Wolvic\",\n        \"ua\"      : \"Mozilla/5.0 (Android 12; Mobile VR; rv:121.0) Gecko/121.0 Firefox/121.0 Wolvic/1.6.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Wolvic\",\n            \"version\" : \"1.6.1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.0.1084.5402 Chrome/19.0.1084.5402 Safari/536.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"1.0.1084.5402\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; arm_64; Android 11; M2101K7AG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.125 YaApp_Android/22.70 YaSearchBrowser/22.70 BroPP/1.0 SA/3 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"22.70\",\n            \"major\"   : \"22\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 YaBrowser/23.3.0.2246 Yowser/2.5 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"23.3.0.2246\",\n            \"major\"   : \"23\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; arm_64; Android 13; SM-G965F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.76 YaBrowser/21.3.4.59 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"21.3.4.59\",\n            \"major\"   : \"21\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex on iPhone\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 YaBrowser/23.3.3.330 Mobile/15E148 Safari/604.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"23.3.3.330\",\n            \"major\"   : \"23\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex on iPad\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU OS 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 YaBrowser/23.3.3.330 Mobile/15E148 Safari/605.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"23.3.3.330\",\n            \"major\"   : \"23\"\n        }\n    },\n    {\n        \"desc\"    : \"Yandex on iPod\",\n        \"ua\"      : \"Mozilla/5.0 (iPod touch; CPU iPhone 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 YaBrowser/23.3.3.330 Mobile/15E148 Safari/605.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yandex\",\n            \"version\" : \"23.3.3.330\",\n            \"major\"   : \"23\"\n        }\n    },\n    {\n        \"desc\"    : \"Puffin\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; Lenovo P2a42 Build/MMB29M; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Puffin/6.0.8.15804AP\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Puffin\",\n            \"version\" : \"6.0.8.15804AP\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Puffin\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.1.1; ZTE BLADE A0620 Build/NMF26F; ru-ru) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36 Puffin/9.2.0.50586AP\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Puffin\",\n            \"version\" : \"9.2.0.50586AP\",\n            \"major\"   : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge 0.1\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"12.0\",\n            \"major\"   : \"12\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge 42\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"17.17134\",\n            \"major\"   : \"17\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge 44\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"18.17763\",\n            \"major\"   : \"18\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge 100\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.1108.55 Safari/537.36 Edg/100.0.1108.55\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"100.0.1108.55\",\n            \"major\"   : \"100\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 EdgiOS/42.1.1.0 Mobile/15F79 Safari/605.1.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"42.1.1.0\",\n            \"major\"   : \"42\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.0.0; G8441 Build/47.1.A.12.270) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.123 Mobile Safari/537.36 EdgA/42.0.0.2529\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"42.0.0.2529\",\n            \"major\"   : \"42\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge Chromium\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.48 Safari/537.36 Edg/74.1.96.24\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge\",\n            \"version\" : \"74.1.96.24\",\n            \"major\"   : \"74\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge WebView\",\n        \"ua\"      : \"Mozilla/5.0 (Windows IoT 10.0; Android 6.0.1; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Mobile Safari/537.36 Edge/18.17763\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge WebView\",\n            \"version\" : \"18.17763\",\n            \"major\"   : \"18\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Edge WebView2\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 11; SM-G991B Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.120 Mobile Safari/537.36 EdgW/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Edge WebView2\",\n            \"version\" : \"91.0.4472.120\",\n            \"major\"   : \"91\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Iridium\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Iridium/43.8 Safari/537.36 Chrome/43.0.2357.132\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iridium\",\n            \"version\" : \"43.8\",\n            \"major\"   : \"43\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) FxiOS/1.1 Mobile/13B143 Safari/601.1.46\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Firefox\",\n            \"version\" : \"1.1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/112.0 Mobile/15E148 Safari/605.1.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Firefox\",\n            \"version\" : \"112.0\",\n            \"major\"   : \"112\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox iOS using iPad\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Firefox\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"QQ on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Mobile/14A456 QQ/6.5.3.410 V1_IPH_SQ_6.5.3_1_APP_A Pixel/1080 Core/UIWebView NetType/WIFI Mem/26\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QQBrowser\",\n            \"version\" : \"6.5.3.410\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"QQ on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0; PRO 6 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.8 TBS/036824 Safari/537.36 V1_AND_SQ_6.5.8_422_YYB_D PA QQ/6.5.8.2910 NetType/WIFI WebP/0.3.0 Pixel/1080\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QQBrowser\",\n            \"version\" : \"6.5.8.2910\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"WeChat Desktop for Windows Built-in Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.901.400 QQBrowser/9.0.2524.400\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WeChat\",\n            \"version\" : \"3.43.901.400\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"WeChat Desktop for Windows Built-in Browser major version in 4\",\n        \"ua\"      : \"mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/53.0.2785.116 safari/537.36 qbcore/4.0.1301.400 qqbrowser/9.0.2524.400 mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/81.0.4044.138 safari/537.36 nettype/wifi micromessenger/7.0.20.1781(0x6700143b) windowswechat\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WeChat\",\n            \"version\" : \"4.0.1301.400\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Supposed not to be detected as WeChat\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.124 Safari/537.36 qblink wegame.exe WeGame/5.1.1.11100 QBCore/3.70.107.400 QQBrowser/9.0.2524.400\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QQBrowser\",\n            \"version\" : \"9.0.2524.400\",\n            \"major\"   : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"GSA on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) GSA/30.1.161623614 Mobile/14F89 Safari/602.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GSA\",\n            \"version\" : \"30.1.161623614\",\n            \"major\"   : \"30\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Sogou Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sogou Explorer\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Sogou Mobile Browser\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 SogouMSE,SogouMobileBrowser/3.7.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sogou Mobile\",\n            \"version\" : \"3.7.4\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"LieBao Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LBBROWSER\"\n        }\n    },\n    {\n        \"desc\"    : \"QQBrowserLite\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14 QQBrowserLite/1.1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QQBrowserLite\",\n            \"version\" : \"1.1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Brave\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 11; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/88.0.4324.96 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Brave\",\n            \"version\" : \"88.0.4324.96\",\n            \"major\"   : \"88\"\n        }\n    },\n    {\n        \"desc\"    : \"Brave\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 11; Samsung Galaxy F62 SM-E625F Build/SME625F512091028;) AppleWebKit/537.36 (KHTML, like Gecko) Brave/1.75.110 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Brave\",\n            \"version\" : \"1.75.110\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Brave Browser\",\n        \"ua\"      : \"Brave/4.5.16 CFNetwork/893.13.1 Darwin/17.3.0 (x86_64)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Brave\",\n            \"version\" : \"4.5.16\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Whale Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.146 Whale/2.6.90.14 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Whale\",\n            \"version\" : \"2.6.90.14\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Electron\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Atom/1.41.0 Chrome/69.0.3497.128 Electron/4.2.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Electron\",\n            \"version\" : \"4.2.7\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"IE11 on Windows 7 (ua length >255)\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64; APCPMS=^N201205020840572565478A37A6F9C41BD33F_9975^; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; MARKANYEPS#25118; Zoom 3.6.0; rv:11.0) like Gecko\",\n        \"expect\"  :\n        {\n            \"name\"    : \"IE\",\n            \"version\" : \"11.0\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"LinkedIn\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [LinkedInApp]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LinkedIn\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Links in Linux\",\n        \"ua\"      : \"Links (2.xpre7; Linux 2.4.18 i586; x)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Links\",\n            \"version\" : \"2.xpre7\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Links in Mac\",\n        \"ua\"      : \"Links (2.1pre33; Darwin 8.11.0 Power Macintosh; 169x55)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Links\",\n            \"version\" : \"2.1pre33\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Links in NetBSD\",\n        \"ua\"      : \"Links (2.29; NetBSD 10.0 i386; GNU C 10.5; x)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Links\",\n            \"version\" : \"2.29\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Links in FreeBSD\",\n        \"ua\"      : \"Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 196x84)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Links\",\n            \"version\" : \"2.1pre15\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Safari including comma in minor version number\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6,2 Safari/605.1.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Safari\",\n            \"version\" : \"15.6,2\",\n            \"major\"   : \"15\"\n        }\n    },\n    {\n        \"desc\"    : \"Mobile Safari including comma in minor version number\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6,2 Mobile/15E148 Safari/604.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Safari\",\n            \"version\" : \"15.6,2\",\n            \"major\"   : \"15\"\n        }\n    },\n    {\n        \"desc\"     : \"Cobalt 23 Master\",\n        \"ua\"       : \"Mozilla/5.0 (X11; Linux x86_64) Cobalt/23.master.0.0-devel (unlike Gecko) v8/8.8.278.8-jit gles Starboard/15\",\n        \"expect\"   : {\n            \"name\"   : \"Cobalt\",\n            \"version\": \"23.0.0\",\n            \"major\"  : \"23\"\n        }\n    },\n    {\n        \"desc\"     : \"Cobalt 23 LTS\",\n        \"ua\"       : \"Mozilla/5.0 (X11; Linux x86_64) Cobalt/23.lts.1.0-qa (unlike Gecko) v8/8.8.278.8-jit gles Starboard/15\",\n        \"expect\"   : {\n            \"name\"   : \"Cobalt\",\n            \"version\": \"23.1.0\",\n            \"major\"  : \"23\"\n        }\n    },\n    {\n        \"desc\"     : \"Cobalt 11\",\n        \"ua\"       : \"Mozilla/5.0 (X11; Linux x86_64) Cobalt/11.0-qa (unlike Gecko) Starboard/6\",\n        \"expect\"   : {\n            \"name\"   : \"Cobalt\",\n            \"version\": \"11.0\",\n            \"major\"  : \"11\"\n        }\n    },\n    {\n        \"desc\"     : \"Cobalt 9\",\n        \"ua\"       : \"Mozilla/5.0 (X11; Linux x86_64) Cobalt/9.0-qa (unlike Gecko) Starboard/4\",\n        \"expect\"   : {\n            \"name\"   : \"Cobalt\",\n            \"version\": \"9.0\",\n            \"major\"  : \"9\"\n        }\n    },\n    {\n        \"desc\"     : \"KakaoTalk App Android\",\n        \"ua\"       : \"Mozilla/5.0 (Linux; Android 12; SM-G988N Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.79 Mobile Safari/537.36;KAKAOTALK 2409760\",\n        \"expect\"   : {\n            \"name\"   : \"KAKAOTALK\",\n            \"version\": \"2409760\",\n            \"major\"  : \"2409760\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"     : \"KakaoStory App Android\",\n        \"ua\"       : \"Mozilla/5.0 (Linux; Android 12; SM-G988N Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.79 Mobile Safari/537.36 KAKAOSTORY/6.8.3_21046\",\n        \"expect\"   : {\n            \"name\"   : \"KAKAOSTORY\",\n            \"version\": \"6.8.3_21046\",\n            \"major\"  : \"6\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"     : \"KakaoTalk App iOS\",\n        \"ua\"       : \"Mozilla/5.0 (iPhone; CPU; iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 BizWebView KAKAOTALK 9.7.6\",\n        \"expect\"   : {\n            \"name\"   : \"KAKAOTALK\",\n            \"version\": \"9.7.6\",\n            \"major\"  : \"9\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"     : \"Naver App Android\",\n        \"ua\"       : \"Mozilla/5.0 (Linux; Android 12; SM-G988N Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.232 Whale/1.0.0.0 Crosswalk/26.90.3.21 Mobile Safari/537.36 NAVER(inapp; search; 1010; 11.11.2)\",\n        \"expect\"   : {\n            \"name\"   : \"NAVER\",\n            \"version\": \"11.11.2\",\n            \"major\"  : \"11\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"     : \"Naver App iOS\",\n        \"ua\"       : \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/605.1 NAVER(inapp; search; 720; 10.25.0; 11PRO)\",\n        \"expect\"   : {\n            \"name\"   : \"NAVER\",\n            \"version\": \"10.25.0\",\n            \"major\"  : \"10\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n      \"desc\"     : \"Daum App Android\",\n      \"ua\"       : \"Mozilla/5.0 (Linux; Android 11; SM-G970N Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 DaumApps/7.5.0 DaumDevice/mobile\",\n      \"expect\"   : {\n        \"name\"   : \"Daum\",\n        \"version\": \"7.5.0\",\n        \"major\"  : \"7\",\n        \"type\"    : \"inapp\"\n      }\n    },\n    {\n      \"desc\"     : \"Daum App iOS\",\n      \"ua\"       : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Safari/605.1.15 Mobile/15E148 DaumApps/7.5.1 DaumDevice/mobile\",\n      \"expect\"   : {\n        \"name\"   : \"Daum\",\n        \"version\": \"7.5.1\",\n        \"major\"  : \"7\",\n        \"type\"    : \"inapp\"\n      }\n    },\n    {\n        \"desc\"     : \"TikTok\",\n        \"ua\"       : \"Mozilla/5.0 (Linux; Android 11; 21061119AG Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile Safari/537.36 trill_2022109040 JsSdk/1.0 NetType/MOBILE Channel/googleplay AppName/musical_ly app_version/21.9.4 ByteLocale/ru-RU ByteFullLocale/ru-RU Region/KG BytedanceWebview/d8a21c6\",\n        \"expect\"   : {\n            \"name\"   : \"TikTok\",\n            \"version\": \"21.9.4\",\n            \"major\"  : \"21\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"     : \"TikTok\",\n        \"ua\"       : \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 musical_ly_21.1.0 JsSdk/2.0 NetType/4G Channel/App Store ByteLocale/ru Region/RU ByteFullLocale/ru-RU isDarkMode/1 WKWebView/1 BytedanceWebview/d8a21c6\",\n        \"expect\"   : {\n            \"name\"   : \"TikTok\",\n            \"version\": \"21.1.0\",\n            \"major\"  : \"21\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"     : \"TikTok\",\n        \"ua\"       : \"Mozilla/5.0 (Linux; Android 10; STK-LX1 Build/HONORSTK-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 musical_ly_2022803040 JsSdk/1.0 NetType/WIFI Channel/huaweiadsglobal_int AppName/musical_ly app_version/28.3.4 ByteLocale/en ByteFullLocale/en Region/IQ Spark/1.2.7-alpha.8 AppVersion/28.3.4 PIA/1.5.11 BytedanceWebview/d8a21c6\",\n        \"expect\"   : {\n            \"name\"   : \"TikTok\",\n            \"version\": \"28.3.4\",\n            \"major\"  : \"28\",\n            \"type\"    : \"inapp\"\n        }\n    },\n      {\n        \"desc\"     : \"TikTok\",\n        \"ua\"       : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari/604.1 trill_43.0.0 BytedanceWebview/d8a21c6\",\n        \"expect\"   : {\n            \"name\"   : \"TikTok\",\n            \"version\": \"43.0.0\",\n            \"major\"  : \"43\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome Mobile\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.1.2; Nexus 5X Build/N2G47W) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Chrome\",\n            \"version\" : \"58.0.3029.83\",\n            \"major\"   : \"58\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox Mobile\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.1.2; Nexus 5X Build/N2G47W) AppleWebKit/537.36 (KHTML, like Gecko) FxiOS/7.5b3349 Mobile/14F89 Safari/603.2.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Firefox\",\n            \"version\" : \"7.5b3349\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox Mobile\",\n        \"ua\"      : \"Mozilla/5.0 (Android 5.0; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mobile Firefox\",\n            \"version\" : \"41.0\",\n            \"major\"   : \"41\"\n        }\n    },\n    {\n        \"desc\"    : \"Snapchat\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Snapchat/12.33.0.36 (like Safari/8614.1.25.0.31, panda)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Snapchat\",\n            \"version\" : \"12.33.0.36\",\n            \"major\"   : \"12\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Twitter\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 13; CPH2531 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.120 Mobile Safari/537.36 TwitterAndroid\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Twitter\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Twitter\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19H12 Twitter for iPhone/10.34\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Twitter\",\n            \"version\" : \"10.34\",\n            \"major\"   : \"10\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Zalo on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Zalo/20.05.01 Mobile/15E148\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Zalo\",\n            \"version\" : \"20.05.01\",\n            \"major\"   : \"20\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Zalo on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; Vsmart Live Build/QKQ1.190918.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 Zalo/20.04.02.r1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Zalo\",\n            \"version\" : \"20.04.02.r1\",\n            \"major\"   : \"20\",\n            \"type\"    : \"inapp\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/cpu/cpu-all.json",
    "content": "[\n    {\n        \"desc\"    : \"i686\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ia32\"\n        }\n    },\n    {\n        \"desc\"    : \"i686\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.253.0 Safari/532.5\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ia32\"\n        }\n    },\n    {\n        \"desc\"    : \"i386\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040628 Epiphany/1.2.6\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ia32\"\n        }\n    },\n    {\n        \"desc\"    : \"x86-64\",\n        \"ua\"      : \"Opera/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto/2.2.15 Version/10.10\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivaldi on Windows\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Vivaldi/6.0.2979.18\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivaldi on Windows\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Vivaldi/6.0.2979.18\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivaldi on Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Vivaldi/6.0.2979.18\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"Vivaldi on Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Vivaldi/6.0.2979.18\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ia32\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO M2 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; POCO M2 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 YaBrowser/22.11.7.42.00 SA/3 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm64\"\n        }\n    },\n    {\n        \"desc\"    : \"win64\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident/6.0; .NET4.0E; .NET4.0C)\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"WOW64\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"Alpha\",\n        \"ua\"      : \"Mozilla/3.01 (WinNT; I) [AXP]\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"alpha\"\n        }\n    },\n    {\n        \"desc\"    : \"Alpha\",\n        \"ua\"      : \"Mozilla/5.0 (X11; OpenBSD alpha; rv:78.0) Gecko/20100101 Firefox/78.0\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"alpha\"\n        }\n    },\n    {\n        \"desc\"    : \"ARM\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"ARMv61\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"ARMv7\",\n        \"ua\"      : \"Mozilla/5.0 (Linux ARMv7) WebKitGTK+/3.4.9 vimprobable2\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"ARMv7l\",\n        \"ua\"      : \"Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebKit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"ARMv7l\",\n        \"ua\"      : \"Mozilla/5.0 (X11; CrOS armv7l 9765.85.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.123 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia N900 Linux mobile\",\n        \"ua\"      : \"Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0) Gecko/20100101 Firefox/10.0 Fennec/10.0\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"ARMEABI\",\n        \"ua\"      : \"[FBAN/FB4A;FBAV/237.0.0.44.120;FBBV/170693408;FBDM/{density=1.75,width=720,height=1280};FBLC/en_US;FBRV/172067074;FBCR/ ;FBMF/samsung;FBBD/samsung;FBPN/com.facebook.katana;FBDV/SM-S367VL;FBSV/9;FBBK/1;FBOP/19;FBCA/armeabi-v7a:armeabi;]\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"ARMv8\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux armv8l; rv:45.0) Gecko/20100101 Firefox/45.0\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm64\"\n        }\n    },\n    {\n        \"desc\"    : \"AARCH64\",\n        \"ua\"      : \"Mozilla/5.0 (X11; CrOS aarch64 13310.93.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.133 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm64\"\n        }\n    },\n    {\n        \"desc\"    : \"ARM64\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; ARM64; RM-1096) AppleWebKit/537.36 (KHTML like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm64\"\n        }\n    },\n    {\n        \"desc\"    : \"ARM64\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; arm_64; Android 9; HRY-LX1T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 YaBrowser/19.12.1.121.00 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm64\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Search App\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 9; JAT-LX1 Build/HONORJAT-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.96 Mobile Safari/537.36 GoogleApp/11.11.10.21.arm\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Search App\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0; M5s Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.147 Mobile Safari/537.36 GSA/12.40.17.23.arm64\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm64\"\n        }\n    },\n    {\n        \"desc\"    : \"Pocket PC\",\n        \"ua\"      : \"Opera/9.7 (Windows Mobile; PPC; Opera Mobi/35166; U; en) Presto/2.2.1\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"arm\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac PowerPC\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 4.5; Mac_PowerPC)\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ppc\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac PowerPC\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.17; Mac_PowerPC Mac OS; en)\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ppc\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac PowerPC\",\n        \"ua\"      : \"iCab/2.9.5 (Macintosh; U; PPC; Mac OS X)\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ppc\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac OS X on PowerPC using Firefox\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; PPC Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"ppc\"\n        }\n    },\n    {\n        \"desc\"    : \"UltraSPARC\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"sparc\"\n        }\n    },\n    {\n        \"desc\"    : \"sparc64\",\n        \"ua\"      : \"ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)\",\n        \"expect\"  :\n        {\n            \"architecture\"  : \"sparc64\"\n        }\n    },\n    {\n        \"desc\"    : \"QuickTime\",\n        \"ua\"      : \"QuickTime/7.5.6 (qtver=7.5.6;cpu=IA32;os=Mac 10.5.8)\",\n        \"expect\"  : \n        {\n            \"architecture\"  : \"ia32\"\n        }\n    },\n    {\n        \"desc\"    : \"XBMC\",\n        \"ua\"      : \"XBMC/12.0 Git:20130127-fb595f2 (Windows NT 6.1;WOW64;Win64;x64; http://www.xbmc.org)\",\n        \"expect\"  : \n        {\n            \"architecture\"  : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"IRIX64\",\n        \"ua\"      : \"Mozilla/4.8C-SGI [en] (X11; U; IRIX64 6.5 IP27\",\n        \"expect\"  : \n        {\n            \"architecture\"  : \"irix64\"\n        }\n    },\n    {\n        \"desc\"    : \"68k\",\n        \"ua\"      : \"Mozilla/1.1 (Macintosh; U; 68K)\",\n        \"expect\"  : \n        {\n            \"architecture\"  : \"68k\"\n        }\n    },\n    {\n        \"desc\"    : \"MC680x0\",\n        \"ua\"      : \"AmigaVoyager/3.2 (AmigaOS/MC680x0)\",\n        \"expect\"  : \n        {\n            \"architecture\"  : \"68k\"\n        }\n    },\n    {\n        \"desc\"    : \"x86\",\n        \"ua\"      : \"Mozilla/5.0 (Photon; U; QNX x86pc; en-US; rv:1.8.1.20) Gecko/20090127 BonEcho/2.0.0.20\",\n        \"expect\"  : \n        {\n            \"architecture\"  : \"ia32\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/device/_others.json",
    "content": "[\n    {\n        \"desc\": \"Generic Android Device\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 9; X96mini_RP Build/X96mini_RP)\",\n        \"expect\": {\n            \"vendor\": \"Generic\",\n            \"model\": \"X96mini_RP\"\n        }\n    },\n    {\n        \"desc\": \"Generic Android Device\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; i980 Build/MRA58K)\",\n        \"expect\": {\n            \"vendor\": \"Generic\",\n            \"model\": \"i980\"\n        }\n    },\n    {\n        \"desc\": \"K\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"K\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Unknown VR Device\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.2; Unknown Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile VR Safari/537.36\",\n        \"expect\": {\n            \"model\": \"Unknown\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Desktop (IE11 with Tablet string)\",\n        \"ua\": \"Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; GWX:MANAGED; rv:11.0) like Gecko\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"undefined\"\n        }\n    },\n    {\n        \"desc\": \"Mobile (DuckDuckGo mobile browser)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.131 Mobile DuckDuckGo/5 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ChangHong Android TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; ChangHong Android TV Build/LMY49J) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/10.8 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"ChangHong\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"MStar Android TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.3.1; MStar Android TV Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.95 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"MStar\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"ONIDA Android TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; ONIDA Android TV Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/48.0.2542.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"ONIDA\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"JVC LT-43V55LFA Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 OPR/40.0.2207.0 OMI/4.9.0.237.DOM3-OPT.245 Model/Vestel-MB211 VSTVB MB200 HbbTV/1.2.1 (; JVC; MB211; 3.19.4.2; _TV_NT72563_2017 SmartTvA/3.0.0\",\n        \"expect\": {\n            \"vendor\": \"JVC\",\n            \"model\": \"MB211\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"JVC LT-43V65LUA Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 OPR/40.0.2207.0 OMI/4.9.0.237.DOM3-OPT.245 Model/Vestel-MB130 VSTVB MB100 HbbTV/1.2.1 (; JVC; MB130; 5.7.20.0; _TV_G10_2017;) SmartTvA/3.0.0\",\n        \"expect\": {\n            \"vendor\": \"JVC\",\n            \"model\": \"MB130\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Loewe Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36 OPR/46.0.2207.0 LOEWE-SL410/5.2.0.0 HbbTV/1.4.1 (; LOEWE; SL410; LOH/5.2.0.0;;) FVC/3.0 (LOEWE; SL410;) CE-HTML/1.0 Config (L:deu,CC:DEU) NETRANGEMMH\",\n        \"expect\": {\n            \"vendor\": \"LOEWE\",\n            \"model\": \"SL410\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Issue #747\",\n        \"ua\": \"python-requests/2.25.1\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"undefined\"\n        }\n    },\n    {\n        \"desc\": \"Issue #454\",\n        \"ua\": \"Mosamzilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20050603 Netscape/8.0.2\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"undefined\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV\",\n        \"ua\": \"Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebkit/537.42 (KHTML, like Gecko) Safari/537.42\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Android Phone Unidentified Vendor (docomo F-04K)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; F-04K Build/V15R060P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36\",\n        \"expect\": {\n            \"model\": \"F-04K\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Android Tablet Unidentified Vendor (docomo F-02K)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; F-02K Build/V44R059G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36\",\n        \"expect\": {\n            \"model\": \"F-02K\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Android Tablet Unidentified Vendor (docomo d-02K)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; d-02K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Safari/537.36\",\n        \"expect\": {\n            \"model\": \"d-02K\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Android TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; 2020/2021 UHD Android TV Build/QTG3.201102.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Mobile using Firefox\",\n        \"ua\": \"Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Tablet using Firefox\",\n        \"ua\": \"Mozilla/5.0 (Android 4.4; Tablet; rv:41.0) Gecko/41.0 Firefox/41.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Mobile using Focus for Android\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Focus/1.0 Chrome/59.0.3029.83 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Tablet using Focus for Android\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Focus/1.0 Chrome/59.0.3029.83 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Device using Focus for Android with GeckoView\",\n        \"ua\": \"Mozilla/5.0 (Android 7.0; Mobile; rv:62.0) Gecko/62.0 Firefox/62.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Mobile using Firefox OS\",\n        \"ua\": \"Mozilla/5.0 (Mobile; rv:26.0) Gecko/26.0 Firefox/26.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Unknown Tablet using Firefox OS\",\n        \"ua\": \"Mozilla/5.0 (Tablet; rv:26.0) Gecko/26.0 Firefox/26.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Unknown TV using Firefox OS\",\n        \"ua\": \"Mozilla/5.0 (TV; rv:44.0) Gecko/44.0 Firefox/44.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Unknown TV\",\n        \"ua\": \"Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Large Screen Safari/533.4 GoogleTV/ 162671\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Unknown TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Unknown VR Device using Firefox Reality\",\n        \"ua\": \"Mozilla/5.0 (Android 10; Mobile VR; rv:123.0) Gecko/123.0 Firefox/123.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Unknown VR Device using Wolvic\",\n        \"ua\": \"Mozilla/5.0 (Android 14; Mobile VR; rv:128.0) Gecko/128.0 Firefox/128.0 Wolvic/1.8\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 HbbTV/1.6.1 ( DRM; LGE/ATMACA/GRAETZ; GR32S1470; WEBOS22 04.41.53; W22_K8AP; DTV_C22L;) LaTivu_1.0.1_2022\",\n        \"expect\": {\n            \"vendor\": \"GRAETZ\",\n            \"model\": \"GR32S1470\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 HbbTV/1.5.1 (+DRM; LGE/DUALSHINE/SKYTECH; ST-5090; WEBOS5.0 04.50.63; W50_K6LP; DTV_C20P;)\",\n        \"expect\": {\n            \"vendor\": \"SKYTECH\",\n            \"model\": \"ST-5090\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 HbbTV/1.6.1 (+DRM; LGE/SILICONPLAYER/Hyundai; 50HYN3205; WEBOS22 04.42.26; W22_K8LP; DTV_C22P;)\",\n        \"expect\": {\n            \"vendor\": \"Hyundai\",\n            \"model\": \"50HYN3205\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"PDA with Windows CE\",\n        \"ua\": \"Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows IoT\",\n        \"ua\"      : \"Mozilla/5.0 (Windows IoT 10.0; Android 6.0.1; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Mobile Safari/537.36 Edge/18.17763\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"undefined\",\n            \"type\": \"embedded\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/acer.json",
    "content": "[\n    {\n        \"desc\": \"Acer Iconia A1-810\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; A1-810 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Acer\",\n            \"model\": \"A1-810\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/advan.json",
    "content": "[\n    {\n        \"desc\": \"Advan M4\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0; ADVAN M4 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36 OPR/28.0.2254.119214\",\n        \"expect\": {\n            \"vendor\": \"ADVAN\",\n            \"model\": \"M4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Advan S40\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; ADVAN S40 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Mobile Safari/537.36 EdgA/79.0.309.58\",\n        \"expect\": {\n            \"vendor\": \"ADVAN\",\n            \"model\": \"S40\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Advan Sketsa 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; ADVAN 1011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ADVAN\",\n            \"model\": \"1011\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/alcatel.json",
    "content": "[\n    {\n        \"desc\": \"Alcatel 4056W\",\n        \"ua\": \"Mozilla/5.0 (Mobile; ALCATEL 4056W; rv:84.0) Gecko/84.0 Firefox/84.0 KAIOS/3.0\",\n        \"expect\": {\n            \"vendor\": \"ALCATEL\",\n            \"model\": \"4056W\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Alcatel A564C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; ALCATEL A564C Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ALCATEL\",\n            \"model\": \"A564C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Alcatel Go Flip\",\n        \"ua\": \"Mozilla/5.0 (Mobile; ALCATEL4044T; rv:37.0) Gecko/37.0 Firefox/37.0 KaiOS/1.0\",\n        \"expect\": {\n            \"vendor\": \"ALCATEL\",\n            \"model\": \"4044T\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/amazon.json",
    "content": "[\n    {\n        \"desc\": \"Kindle Fire HD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KFTT\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Kindle Fire HD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KFTT\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Echo Show 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; AEORK Build/LVY48F; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"AEORK\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Echo Show 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1; AEOCH) AppleWebKit/537.36 (KHTML, like Gecko) Silk/77.2.21 like Chrome/77.0.3865.92 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"AEOCH\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Echo Show 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.2; AEOCW) AppleWebKit/537.36 (KHTML, like Gecko) Silk/106.3.3 like Chrome/106.0.5249.170 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"AEOCW\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Echo Show 15\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; AEOHY) AppleWebKit/537.36 (KHTML, like Gecko) Silk/112.6.3 like Chrome/112.0.5615.213 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"AEOHY\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Echo Dot\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEOBC Build/LVY48F)\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"AEOBC\",\n            \"type\": \"embedded\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Kindle Fire Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.66 like Chrome/39.0.2171.93 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KFSAWI\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Kindle Fire Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.66 like Chrome/39.0.2171.93 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KFSAWI\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Kindle Fire Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; KFMAWI Build/PS7312; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KFMAWI\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Fire TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; AFTB Build/JDQ39) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.173 Mobile Safari/537.22\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"B\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Fire TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; AFTT) AppleWebKit/537.36 (KHTML, like Gecko) Silk/86.3.20 like Chrome/86.0.4240.198 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"T\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Fire TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; AFTKA Build/PS7633.3445N; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.160 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KA\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Fire 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; KFAUWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/80.5.3 like Chrome/80.0.3987.162 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"KFAUWI\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Amazon Alexa Echo Show\",\n        \"ua\": \"AlexaWebMediaPlayer/1.0.200641.0 (Linux;Android 5.1.1)\",\n        \"expect\": {\n            \"vendor\": \"Amazon\",\n            \"model\": \"Alexa\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/anbernic.json",
    "content": "[\n    {\n        \"desc\": \"Anbernic\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; RGCUBE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Anbernic\",\n            \"model\": \"RGCUBE\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/apple.json",
    "content": "[\n    {\n        \"desc\": \"Apple Desktop\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"Macintosh\",\n            \"type\": \"undefined\"\n        }\n    },\n    {\n        \"desc\": \"Apple Watch\",\n        \"ua\": \"atc/1.0 watchOS/7.3.3 model/Watch4,2 hwp/t8006 build/18S830 (6; dt:191)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"watch\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"iPad using UCBrowser\",\n        \"ua\": \"Mozilla/5.0 (iPad; U; CPU OS 11_2 like Mac OS X; zh-CN; iPad5,3) AppleWebKit/534.46 (KHTML, like Gecko) UCBrowser/3.0.1.776 U3/ Mobile/10A403 Safari/7543.48.3\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad Air\",\n        \"ua\": \"Mozilla/5.0 (iPad; CPU OS 12_4_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPad4,1;FBMD/iPad;FBSN/iOS;FBSV/12.4.5;FBSS/2;FBID/tablet;FBLC/en_US;FBOP/5;FBCR/]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using Facebook Browser\",\n        \"ua\": \"Mozilla/5.0 (iPad; CPU OS 14_4_2 like Mac OS X) WebKit/8610 (KHTML, like Gecko) Mobile/18D70 [FBAN/FBIOS;FBDV/iPad7,11;FBMD/iPad;FBSN/iOS;FBSV/14.4.2;FBSS/2;FBID/tablet;FBLC/en_US;FBOP/5]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using Chrome\",\n        \"ua\": \"Mozilla/5.0 (iPad13,10; CPU OS 16_6_2 like Mac OS X) AppleWebKit/602.3 (KHTML, like Gecko) CriOS/97.0.0.5927.72 Mobile/11S296 Safari/602.3\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using DuckDuckGo\",\n        \"ua\": \"Mozilla/5.0 (iPad; iPad13,6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) DuckDuckGo/130.0.0.0 Mobile/15E148 Safari/604.1\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using Discord\",\n        \"ua\": \"Discord/52.0 (iPad; iOS 14.4; Scale/2.00)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using Firefox\",\n        \"ua\": \"Mozilla/5.0 (iPad; iPad14,2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Firefox/120.0 Mobile/15E148 Safari/604.1\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using iTunes\",\n        \"ua\": \"itunesstored/1.0 iOS/15.6.1 model/iPad13,8 hwp/t8103 build/19G82 (5; dt:238)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using MS OneNote\",\n        \"ua\": \"Microsoft Office OneNote/16.81/240108 (iOS/16.5.1; Tablet; AppStore; Apple/iPad8,3)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using MS Word\",\n        \"ua\": \"Microsoft Office Word/2.44.1211 (iOS/13.7; Tablet; es-MX; AppStore; Apple/iPad11,3)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using Quora\",\n        \"ua\": \"Quora 8.4.30 rv:3230 env:prod (iPad11,3; iPadOS 17.7; en_GB) AppleWebKit\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using TuneIn Radio\",\n        \"ua\": \"TuneIn Radio/27.1.0; iPad6,3; iPadOS/16.6\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using TuneIn Radio Pro\",\n        \"ua\": \"TuneIn Radio Pro/21.4.1; iPad8,9; iOS/15.0\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPad using YouTube\",\n        \"ua\": \"com.google.ios.youtube/20.31.6 (iPad13,5; U; CPU iPadOS 18_6 like Mac OS X; en_US)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"iPod\",\n        \"ua\": \"Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPod touch\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPhone\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPhone using Spotify\",\n        \"ua\": \"Spotify/8.7.70 iOS/16.0 (iPhone15,3)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone15,3\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPhone SE\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone8,4;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPhone SE using Facebook App\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone8,4;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPhone 11 Pro Max\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone12,5;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPhone XS\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone11,2;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"iPod touch\",\n        \"ua\": \"Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPod touch\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"FaceBook Mobile App\",\n        \"ua\": \"[FBAN/FBIOS;FBAV/283.0.0.44.117;FBBV/238386386;FBDV/iPhone12,1;FBMD/iPhone;FBSN/iOS;FBSV/13.6.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBRV/240127608]\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone12,1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Apple HomePod\",\n        \"ua\": \"AppleCoreMedia/1.0.0.15D61 (HomePod; U; CPU OS 11_2_5 like Mac OS X; en_us)\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"HomePod\",\n            \"type\": \"embedded\"\n        }\n    },\n    {\n        \"desc\": \"Issue #519\",\n        \"ua\": \"ios/iPhone/14.2/SOME_CUSTOM_APP_VERSION\",\n        \"expect\": {\n            \"vendor\": \"Apple\",\n            \"model\": \"iPhone\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/archos.json",
    "content": "[\n    {\n        \"desc\": \"Archos 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 1.6; fr-fr; Archos5 Build/Donut) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"5\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 40b Titanium Surround\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; Archos 40b Titanium Surround Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"40b Titanium Surround\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 40c Titanium v2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; ARCHOS 40C TIv2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"40C TIv2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 45 Neon\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Archos 45 Neon Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"45 Neon\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 45 Neon\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; AC45NE Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 YaBrowser/15.6.2311.6088.00 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"AC45NE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 45B Helium\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; AC45BHE Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"AC45BHE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 45B Titanium\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Archos 45B Titanium) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"45B Titanium\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 50 Cesium\",\n        \"ua\": \"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; ARCHOS; AC50CE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"AC50CE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 50B Helium 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.4; AC50BHE Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"AC50BHE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 55 diamond Selfie\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Archos 55 diamond Selfie Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"55 diamond Selfie\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Archos 80 G9\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.4; zh-tw; ARCHOS 80G9 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"80G9\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 80 Xenon\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.1.2; Archos 80 Xenon Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Safari/537.36 OPR/50.6.2426.201126\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"80 Xenon\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 97c Platinum\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Archos 97c Platinum Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"97c Platinum\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 101 Access 3G V2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; Archos Access 101 3G V2 Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.130 Safari/537.36[FBAN/EMA;FBLC/pt_PT;FBAV/360.0.0.7.53;]\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"Access 101 3G V2\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 101 Oxygen 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; Archos 101 Oxygen 4G Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/103.0.5060.71 Safari/537.36 [FB_IAB/FB4A;FBAV/374.0.0.20.109;]\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"101 Oxygen 4G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 101 Platinum 3G V2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; AC101PL3GV2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"AC101PL3GV2\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 101B Helium 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; AC101BHE Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"AC101BHE\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos 101s Oxygen Ardoiz\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Archos Oxygen 101S ARDOIZ Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.102 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"Oxygen 101S ARDOIZ\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos GAMEPAD2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; ARCHOS GAMEPAD2 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.94 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"GAMEPAD2\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos Hello 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; Archos Hello 7 Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/103.0.5060.53 Safari/537.36 GoogleApp/13.24.9.26.arm64\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"Hello 7\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos Sense 101 X\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 7.0; Archos Sense 101 X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 YaBrowser/20.2.0.215.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"Sense 101 X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos T101 FHD WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; ARCHOS T101 FHD WiFi Build/T00624; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.159 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"T101 FHD WiFi\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos Tikeasy 10d\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; Tikeasy 10d Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.260 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"Tikeasy 10d\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos T96 WIFI\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; ARCHOS T96 WIFI_EEA Build/RP1A.201005.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.78 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"T96 WIFI_EEA\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Archos X67 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; X67 5G Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.58 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Archos\",\n            \"model\": \"X67 5G\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/asus.json",
    "content": "[\n    {\n        \"desc\": \"ASUS Nexus 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"Nexus 7\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Padfone\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.1.1; PadFone 2 Build/JRO03L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"PadFone\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"ASUS ZenPad 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; P00C Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"P00C\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"ASUS ZenPad Z8s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; ASUS_P00J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.111 Safari/537.36\\n\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"P00J\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"ASUS ROG\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; ZS600KL Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"ZS600KL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS ROG II\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; ASUS_I001DA Build/PKQ1.190414.001; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"I001DA\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0; ASUS ZenFone 2 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"ZenFone 2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone 3 Deluxe\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; ASUS_Z016D Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"Z016D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0; ZE620KL Build/OPR1.170623.032) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"ZE620KL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; ASUS_I002D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.81 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"I002D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone 7 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; ZS671KS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"ZS671KS\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone Max Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; ZB602KL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"ZB602KL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone Max Pro (M1)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; ASUS_X00TD Build/OPM1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"X00TD\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone Max M2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; ASUS_X01AD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"X01AD\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone Max Pro M2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; ASUS_X01BDA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"X01BDA\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone Go\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; ASUS_X009DA Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"X009DA\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS Zenfone 2 Laser\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; ASUS_Z00ED) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"Z00ED\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"ASUS ZenWatch\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.1; ASUS ZenWatch Build/LWX48S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/19.77.34.5 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"ASUS\",\n            \"model\": \"ZenWatch\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/blackberry.json",
    "content": "[\n    {\n        \"desc\": \"BlackBerry 9650\",\n        \"ua\": \"Mozilla/5.0 (BlackBerry; U; BlackBerry 9650; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.524 Mobile Safari/534.8+\",\n        \"expect\": {\n            \"vendor\": \"BlackBerry\",\n            \"model\": \"9650\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BlackBerry 9780\",\n        \"ua\": \"Mozilla/5.0 (BlackBerry; U; BlackBerry 9780; en) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.546 Mobile Safari/534.8+\",\n        \"expect\": {\n            \"vendor\": \"BlackBerry\",\n            \"model\": \"9780\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BlackBerry Priv\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; STV100-1 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/46.0.2490.76 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BlackBerry\",\n            \"model\": \"STV100-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BlackBerry Keyone\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; BBB100-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.111 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BlackBerry\",\n            \"model\": \"BBB100-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BlackBerry Key2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; BBF100-1 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.91 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BlackBerry\",\n            \"model\": \"BBF100-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BlackBerry Key2 LE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; BBE100-1 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BlackBerry\",\n            \"model\": \"BBE100-1\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/blackview.json",
    "content": "[\n    {\n        \"desc\": \"Blackview BV4800 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; BV4800 SE Build/AP3A.240905.015.A2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/144.0.7559.94 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/545.0.0.43.63;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Blackview\",\n            \"model\": \"BV4800 SE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Blackview BV9000Pro-F\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.1.1; en-US; BV9000Pro-F Build/N4F26M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/13.1.2.1293 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Blackview\",\n            \"model\": \"BV9000Pro-F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Blackview 4900Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; BV4900Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Blackview\",\n            \"model\": \"BV4900Pro\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/blu.json",
    "content": "[\n    {\n        \"desc\": \"BLU Grand X LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; BLU Grand X LTE Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"Grand X LTE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU Neo Energy Mini\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; BLU_NEO_ENERGY_MINI Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.54 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"NEO_ENERGY_MINI\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU NEO X PLUS\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; BLU NEO X PLUS Build/N090U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"NEO X PLUS\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU STUDIO X MINI\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; BLU STUDIO X MINI Build/S0150UU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"STUDIO X MINI\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU Tank Mega\",\n        \"ua\": \"Mozilla/5.0 (Mobile; BLU_TankMega_3G; rv:48.0; CAEN) Gecko/48.0 Firefox/48.0 KAIOS/2.5.1.1\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"TankMega_3G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU TOUCHBOOK G7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0; BLU TOUCHBOOK G7 Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.107 Safari/537.36 OPR/29.0.1809.91837\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"TOUCHBOOK G7\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU Vivo 5 Mini\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; Vivo 5 Mini Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"Vivo 5 Mini\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU VIVO AIR LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.2; BLU VIVO AIR LTE Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.107 Mobile Safari/537.36 OPR/29.0.1809.91837\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"VIVO AIR LTE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU VIVO GO\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9; VIVO GO Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/72.0.3626.121 Mobile Safari/537.36 OPR/50.0.2254.149182\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"VIVO GO\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU Vivo One Plus 2019\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; Vivo One Plus 2019 Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/277.0.0.41.126;]\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"Vivo One Plus 2019\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"BLU VIVO SELFIE\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.0; es-LA; BLU VIVO SELFIE Build/LRX21M) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/11.3.5.972 U3/0.8.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"BLU\",\n            \"model\": \"VIVO SELFIE\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/cat.json",
    "content": "[\n    {\n        \"desc\": \"Cat B15Q\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; B15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Cat\",\n            \"model\": \"B15Q\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Cat B35\",\n        \"ua\": \"Mozilla/5.0 (Mobile; CAT B35; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5.1\",\n        \"expect\": {\n            \"vendor\": \"Cat\",\n            \"model\": \"B35\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Cat S22 Flip\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; S22 FLIP Build/RKQ1.210416.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.165 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Cat\",\n            \"model\": \"S22 FLIP\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Cat S62 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; S62 Pro Build/RKQ1.210406.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.85 Mobile Safari/537.36 GSA/12.34.17.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"Cat\",\n            \"model\": \"S62 Pro\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/coolpad.json",
    "content": "[\n    {\n        \"desc\": \"Coolpad 10A\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; pt-pt; Coolpad_2041 Build/RP1A.201005.001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36 PHX/12.6\",\n        \"expect\": {\n            \"vendor\": \"Coolpad\",\n            \"model\": \"2041\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Coolpad F2\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; Coolpad 8675-FHD Build/AnZhi) AppleWebKit/534.30 (KHTML like Gecko) Version/4.0 UCBrowser/10.2.0.535 U3/0.8.0 Mobile Safari/534.30 \",\n        \"expect\": {\n            \"vendor\": \"Coolpad\",\n            \"model\": \"8675-FHD\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Coolpad Note 5 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Coolpad 3505I Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.105 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/332.0.0.23.111;]\",\n        \"expect\": {\n            \"vendor\": \"Coolpad\",\n            \"model\": \"3505I\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Coolpad V1-C\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; Coolpad V1-C Build/KTU84P) AppleWebKit/534.24 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.24 T5/2.0 baidubrowser/5.6.4.0 (Baidu; P1 4.4.4)\",\n        \"expect\": {\n            \"vendor\": \"Coolpad\",\n            \"model\": \"V1-C\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/cubot.json",
    "content": "[\n    {\n        \"desc\": \"CUBOT ECHO\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; CUBOT ECHO Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.115 Mobile Safari/537.36 GSA/12.28.8.23.arm\",\n        \"expect\": {\n            \"vendor\": \"CUBOT\",\n            \"model\": \"ECHO\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"CUBOT MAGIC\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.0; CUBOT MAGIC Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36 OPR/36.1.2254.130118\",\n        \"expect\": {\n            \"vendor\": \"CUBOT\",\n            \"model\": \"MAGIC\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"CUBOT NOTE Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; CUBOT NOTE Plus Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/181.0.0.36.82;]\",\n        \"expect\": {\n            \"vendor\": \"CUBOT\",\n            \"model\": \"NOTE Plus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"CUBOT NOVA\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; CUBOT_NOVA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.166 Mobile Safari/537.36 OPR/65.2.3381.61420\",\n        \"expect\": {\n            \"vendor\": \"CUBOT\",\n            \"model\": \"NOVA\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"CUBOT POWER\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; CUBOT_POWER Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.73 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"CUBOT\",\n            \"model\": \"POWER\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"CUBOT X18_Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 8.0.0; CUBOT_X18_Plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 YaBrowser/19.12.1.121.00 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"CUBOT\",\n            \"model\": \"X18_Plus\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/energizer.json",
    "content": "[\n    {\n        \"desc\": \"Energizer Energy 400\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Energy400 Build/MRA58K test-keys; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/172.0.0.66.93;]\",\n        \"expect\": {\n            \"vendor\": \"Energizer\",\n            \"model\": \"Energy400\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Energizer Energy 400S\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Energy 400S Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.85 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Energizer\",\n            \"model\": \"Energy 400S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Energizer Ultimate 65G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Energizer Ultimate 65G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Energizer\",\n            \"model\": \"Ultimate 65G\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/facebook.json",
    "content": "[\n    {\n        \"desc\": \"Oculus Quest\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Quest) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/15.0.0.0.22.280317669 SamsungBrowser/4.0 Chrome/89.0.4389.90 VR Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Facebook\",\n            \"model\": \"Quest\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Oculus Quest 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Quest 2) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/15.0.0.0.22.280317669 SamsungBrowser/4.0 Chrome/89.0.4389.90 VR Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Facebook\",\n            \"model\": \"Quest 2\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Oculus Quest 3\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Quest 3) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/31.4.0.6.51.566757996 Chrome/120.0.6099.283 VR Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Facebook\",\n            \"model\": \"Quest 3\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Oculus Quest Pro\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Quest Pro) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/24.4.0.22.60.426469926 SamsungBrowser/4.0 Chrome/106.0.5249.181 VR Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Facebook\",\n            \"model\": \"Quest Pro\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Portal TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; PortalTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.120 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Facebook\",\n            \"model\": \"PortalTV\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/fairphone.json",
    "content": "[\n    {\n        \"desc\": \"Fairphone 1U\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; FP1U Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Fairphone\",\n            \"model\": \"FP1U\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Fairphone 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.2; FP2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Fairphone\",\n            \"model\": \"FP2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Fairphone 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; FP3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Fairphone\",\n            \"model\": \"FP3\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/google.json",
    "content": "[\n    {\n        \"desc\": \"Google Chromecast with Google TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12.0; Build/STTL.240206.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.0 Safari/537.36 CrKey/1.56.500000 DeviceType/AndroidTV\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Chromecast AndroidTV\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Google Chromecast Mini Smart Speaker\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000 DeviceType/SmartSpeaker\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Chromecast SmartSpeaker\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Google Chromecast Third Generation\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000 DeviceType/Chromecast\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Chromecast Third Generation\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Google Chromecast Nest Hub\",\n        \"ua\": \"Mozilla/5.0 (Fuchsia) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 CrKey/1.56.500000\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Chromecast Nest Hub\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Google Chromecast\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.84 Safari/537.36 CrKey/1.22.79313\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Chromecast\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; Pixel C Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel C\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; Pixel C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel C\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1; Pixel Build/NDE63V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; Pixel 2 Build/OPM1.171019.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Pixel 2) AppleWebKit/537.36 (KHTML, like Gecko) Edg/57.0.986.6\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.2; G011A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Safari/537.36 OPR/68.3.3557.64528\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G011A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 2 XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; Pixel 2 XL Build/OPM1.171019.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 2 XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 2 XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Pixel 2 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 2 XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PD1A.180720.030) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 3\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; G013A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G013A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; G020E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G020E\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3 XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Pixel 3 XL Build/PD1A.180720.030) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 3 XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3 XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Pixel 3 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 3 XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Pixel 3a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 3a\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 3a XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Pixel 3a XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 3a XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; G020M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G020M\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 4a\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; G025J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G025J\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; GA02099) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GA02099\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; G025N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G025N\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4a (5G)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel 4a (5G) Build/UP1A.231105.001.B2; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36 EdgA/124.0.2478.64\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 4a (5G)\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 4 XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 4 XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; G5NZ6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G5NZ6\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; GD1YQ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GD1YQ\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; GTT9Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GTT9Q\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.120 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 5\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 5a 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; G4S1M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G4S1M\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 5a 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; G1F8F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G1F8F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Pixel 6 Build/QP1A.190711.020) AppleWebKit/545.31 (KHTML, like Gecko) Firefox/109.0.2318.118 Mobile Safari/545.22\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 6\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 6 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; Pixel 6 Pro Build/AP4A.241205.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.163 Mobile Safari/537.36 Line/15.0.0/IAB\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 6 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 6 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; G8VOU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G8VOU\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 7\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 7 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; Pixel 7 Pro Build/AP4A.250205.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.121 Mobile Safari/537.36 musical_ly_2023808030 BytedanceWebview/d8a21c6\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 7 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 7 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; GP4BC) AppleWebKit/537.46 (KHTML, like Gecko) Chrome/118.0.5993.80 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GP4BC\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 7 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; GE2AE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.48 Mobile Safari/537.46\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GE2AE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 7a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel 7a Build/AP2A.240905.003; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36 EdgA/124.0.2478.64\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 7a\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel 8 Build/UPB2.230407.014) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.2.7822.95 Mobile Safari/537.36 Vivaldi/5.2.9076.131\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 8\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UPB1.230309.017; Rooted) AppleWebKit/537.36 (KHTML, like Gecko) Puffin/10.9.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 8 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 8a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Google Pixel 8a) Chrome/121.0.6167 Mobile\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 8a\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 8a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GKV4X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GKV4X\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 8a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; G8HHN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G8HHN\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 8a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; G576D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G576D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; Pixel 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.119 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 9\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; G2YBB) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G2YBB\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GUR25) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GUR25\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GWVK6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GWVK6\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; G1B60) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"G1B60\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel 9 Pro Build/AD1A.240530.047; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.170 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/506.1.0.74.27;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 9 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GR83Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GR83Y\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GEC77) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GEC77\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro Fold\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel 9 Pro Fold) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 9 Pro Fold\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro Fold\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GC15S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GC15S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro Fold\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; GGH2X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"GGH2X\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel 9 Pro XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; Pixel 9 Pro XL Build/AP4A.250105.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.89 Mobile Safari/537.36 OPR/88.0.2254.75874\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel 9 Pro XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel Fold\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; Pixel Fold Build/AP4A.250105.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.97 Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.40.36;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel Fold\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Pixel Tablet Build/AP2A.240905.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel Tablet\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel Watch\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 13; Google Pixel Watch Build/TWD4.231005.002)\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel Watch\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel Watch 2\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 13; Google Pixel Watch 2 Build/TWD9.240605.001.A1)\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel Watch 2\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1; Pixel XL Build/NDE63X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixel XL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Pixel XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixel XL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixelbook\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Google Pixelbook) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixelbook\",\n            \"type\": \"undefined\"\n        }\n    },\n    {\n        \"desc\": \"Google Pixelbook Go\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Google Pixelbook Go) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 OPR/62.3.3146.57763\",\n        \"expect\": {\n            \"vendor\": \"Google\",\n            \"model\": \"Pixelbook Go\",\n            \"type\": \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/hisense.json",
    "content": "[\n    {\n        \"desc\": \"Hisense E50 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Hisense E50 Lite) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.126 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Hisense\",\n            \"model\": \"E50 Lite\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Hisense V40s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Hisense V40s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.125 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Hisense\",\n            \"model\": \"V40s\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/hmd.json",
    "content": "[\n    {\n        \"desc\": \"HMD Barbie Phone\",\n        \"ua\": \"Mozilla/5.0 (Mobile; HMD Barbie Phone; rv:84.0) Gecko/84.0 Firefox/84.0 KAIOS/3.1\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"Barbie Phone\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HMD Fusion\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; HMD Fusion) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"Fusion\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HMD Pulse\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; HMD Pulse) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"Pulse\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HMD Pulse Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; HMD Pulse Plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"Pulse Plus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HMD Pulse Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; HMD Pulse Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"Pulse Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HMD Skyline\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 14; HMD Skyline) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.1804 YaApp_Android/24.120.1 YaSearchBrowser/24.120.1 BroPP/1.0 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"Skyline\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HMD Vibe\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; N159V Build/UKQ1.231025.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.7049.111 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.47.36;]\",\n        \"expect\": {\n            \"vendor\": \"HMD\",\n            \"model\": \"N159V\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/honor.json",
    "content": "[\n    {\n        \"desc\": \"Honor MagicPad 13 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 13; zh-CN; GDI-W09 Build/HONORGDI-W09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/16.3.9.1290 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"GDI-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; en-nz; JDN-W09 Build/HuaweiMediaPad) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/6.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"JDN-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9; zh-Hans-CN; JDN2-W09HN Build/HUAWEIJDN2-W09HN) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/4.6.6.164 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"JDN2-W09HN\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad 7 10.1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; AGM3-AL09HN Build/HONORAGM3-AL09HN; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.46 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/490.0.0.63.82;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"AGM3-AL09HN\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad 8 12.0\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; HEY-W09 Build/HONORHEY-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"HEY-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad 9 12.1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; HEY2-N09 Build/HONORHEY2-N09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36 [FB_IAB/FB4A;FBAV/465.0.0.63.83;]\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"HEY2-N09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad 9 12.1 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; HEY2-W09 Build/HONORHEY2-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.102 Safari/537.36 [FB_IAB/FB4A;FBAV/489.0.0.66.81;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"HEY2-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad V7 Pro 11\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; BRT-AN09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 EdgA/109.0.1518.53\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"BRT-AN09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad V7 Pro 11 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; zh-Hans-CN; BRT-W09 Build/HONORBRT-W09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 Quark/6.5.0.336 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"BRT-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad X6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGR-W09HN Build/HUAWEIAGR-W09HN; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.9 SP-engine/2.28.0 baiduboxapp/12.9.0.11 (Baidu; P1 10) NABar/1.0\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"AGR-W09HN\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad X7 8 LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; KOB2-AL00HN; HMSCore 6.0.0.306) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 HuaweiBrowser/11.1.3.300 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"KOB2-AL00HN\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad X7 8 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; KOB2-W09HN; HMSCore 6.1.0.314) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.105 HuaweiBrowser/12.0.0.301 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"KOB2-W09HN\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad X8 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; AGM-W09HN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"AGM-W09HN\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad X9 11.5 LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; ELN-L09 Build/HONORELN-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.86 Mobile Safari/537.36[FBAN/EMA;FBLC/zh_CN;FBAV/432.0.0.9.110;FBCX/modulariab;]\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"ELN-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Honor Pad X9 11.5 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; ELN-W09 Build/HONORELN-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.86 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"ELN-W09\",\n            \"type\": \"tablet\"\n        }\n    },    \n    {\n        \"desc\": \"Huawei Honor 6A\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; DLI-L22 Build/HONORDLI-L22; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/252.0.0.22.355;]\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"DLI-L22\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Honor 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; PLK-L01 Build/HONORPLK-L01; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"PLK-L01\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei 10 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; HRY-LX1 Build/HONORHRY-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.91 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Honor\",\n            \"model\": \"HRY-LX1\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/htc.json",
    "content": "[\n    {\n        \"desc\": \"HTC Desire 820\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; HTC Desire 820 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HTC\",\n            \"model\": \"Desire 820\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HTC Evo Shift 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0\",\n        \"expect\": {\n            \"vendor\": \"Sprint\",\n            \"model\": \"APA7373KT\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HTC Nexus 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0; Nexus 9 Build/LRX21R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Mobile Crosswalk/7.36.154.13 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"HTC\",\n            \"model\": \"Nexus 9\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/huawei.json",
    "content": "[\n    {\n        \"desc\": \"Huawei Honor\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 2.3; xx-xx; U8860 Build/HuaweiU8860) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"U8860\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Honor 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YAL-L41) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YAL-L41\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Honor 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YAL-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YAL-AL10\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nexus 6P\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MTC19V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Mobile Safari/537\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"Nexus 6P\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; VTR-L09 Build/HUAWEIVTR-L09; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"VTR-L09\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y3II\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.1; xx-xx; HUAWEI LUA-L03 Build/HUAWEILUA-L03) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LUA-L03\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad C5 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; MON-AL19B Build/HUAWEIMON-AL19; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/11.7 baiduboxapp/11.7.0.10 (Baidu; P1 7.0)\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"MON-AL19B\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M2 10.1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; HUAWEI M2-A01L Build/HUAWEIM2-A01L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/95.0.4638.74 Safari/537.36[FBAN/EMA;FBLC/fr_FR;FBAV/421.0.0.14.100;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"M2-A01L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M3\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0; en-US; BTV-DL09 Build/HUAWEIBEETHOVEN-DL09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.5.0.1015 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BTV-DL09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M3 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; HUAWEI BTV-W09 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.96 Mobile Safari/537.36 AlohaBrowser/3.1.1\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BTV-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M3 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; CPN-L09 Build/HUAWEICPN-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36[FBAN/EMA;FBLC/ru_RU;FBAV/233.0.0.12.118;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"CPN-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M3 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; CPN-W09 Build/HUAWEICPN-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/103.0.5060.71 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/374.0.0.20.109;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"CPN-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M3 Lite 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; BAH-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M5 10.8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; CMR-W09 Build/HUAWEICMR-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.102 Safari/537.36 Line/14.18.1/IAB\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"CMR-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M5 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; BAH2-W19 Build/HUAWEIBAH2-W19; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH2-W19\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M5 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; JDN2-W09 Build/HUAWEIJDN2-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/318.0.0.39.154;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"JDN2-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M5 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; JDN2-AL50 Build/HUAWEIJDN2-AL50; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.13.0 SP-engine/2.29.0 matrixstyle/0 lite baiduboxapp/5.8.0.10 (Baidu; P1 9) NABar/1.\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"JDN2-AL50\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M5 8.4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SHT-W09 Build/HUAWEISHT-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"SHT-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SHT-AL09 Build/HUAWEISHT-AL09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"SHT-AL09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M6 10.8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; SCM-W09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6612.143 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"SCM-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad M6 8.4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; VRD-W09; HMSCore 6.14.0.321; GMSCore 22.26.15) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"VRD-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; AGS2-L09 Build/HUAWEIAGS2-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/84.0.4147.125 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS2-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; en-US; AGR-L09 Build/HUAWEIAGR-L09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.3.8.1305 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGR-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGR-W09 Build/HUAWEIAGR-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGR-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGS3-W09 Build/HUAWEIAGS3-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS3-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T 8.0\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; KOB2-L09 Build/HUAWEIKOB2-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.105 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/396.0.0.21.104;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"KOB2-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T 8.0\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; KOB2-W09 Build/HUAWEIKOB2-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.105 Mobile Safari/537.36 HuaweiBrowser/15.0.4.312 HMSCore/6.14.0.301\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"KOB2-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T1 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.4; T1-A21w Build/HuaweiMediaPad) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Safari/537.36 SputnikBrowser/1.2.8.161\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"T1-A21w\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T1 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; T1-A23L Build/HuaweiMediaPad; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 BingWeb/6.9.10\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"T1-A23L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T1 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; T1-A21L Build/HuaweiMediaPad) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"T1-A21L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T1 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; 4.4.2; T1-701u) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"T1-701u\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T1 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9.0; MediaPad T1 8.0 Build/HuaweiMediaPad) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30 OPR/28.0.2254.119224\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"MediaPad T1 8.0\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10 9.7\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; en-US; AGRK-L09 Build/HUAWEIAGRK-L09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.6.0.1315 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGRK-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10 9.7 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGRK-W09; HMSCore 6.14.0.321) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGRK-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10s 10.1 LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGS3K-L09 Build/HUAWEIAGS3K-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.105 Safari/537.36 [FB_IAB/FB4A;FBAV/362.0.0.27.109;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS3K-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T10s 10.1 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGS3K-W09; HMSCore 6.14.0.321) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS3K-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T2 10.0 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; 605HW Build/HuaweiMediaPad; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.78 Safari/537.36 [FB_IAB/FB4A;FBAV/436.0.0.35.101;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"605HW\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T2 7.0 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; BGO-DL09 Build/HuaweiBAGGIO; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/407.0.0.30.97;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BGO-DL09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T3 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; AGS-W09 Build/HUAWEIAGS-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.90 Safari/537.36 GSA/10.83.10.21.arm64\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T3 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; BG2-U03 Build/HUAWEIBG2-U03; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/84.0.4147.111 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BG2-U03\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T3 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; KOB-W09 Build/HUAWEIKOB-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Safari/537.36 [FB_IAB/Orca-Android;FBAV/354.0.0.10.113;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"KOB-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad T5 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; AGS2-W09 Build/HUAWEIAGS2-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36 Flipboard/4.3.31/5486,4.3.31.5486\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS2-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"HUAWEI MediaPad X2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0; GEM-703L Build/HUAWEIGEM-703L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043906 Mobile Safari/537.36 MicroMessenger/6.6.3.1260(0x26060339) NetType/WIFI Language/zh_\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"GEM-703L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; HarmonyOS; BAH3-W09; HMSCore 6.14.0.322) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH3-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; HarmonyOS; BAH3-L09; HMSCore 6.14.0.322) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH3-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; BAH3-W59 Build/HUAWEIBAH3-W59; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.105 Safari/537.36HiSearch/22.0.6.315\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH3-W59\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4 (2022)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; BAH4-L09 Build/HUAWEIBAH4-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.105 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH4-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4 (2022) WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; HarmonyOS; BAH4-W09; HMSCore 6.14.0.322) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BAH4-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; AGS5-L09 Build/HUAWEIAGS5-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.88 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS5-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 10.4 SE WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; AGS5-W09 Build/HUAWEIAGS5-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.88 Safari/537.36 [FB_IAB/FB4A;FBAV/480.0.0.54.88;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS5-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 11 (2023) WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; zh-Hans-CN; DBR-W10 Build/HUAWEIDBR-W10) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 Quark/6.9.6.501 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"DBR-W10\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 11 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; zh-cn; DBY-W09 Build/HUAWEIDBY-W09) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.86 MQQBrowser/14.6 Mobile Safari/537.36 COVC/046801\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"DBY-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 11.5 Air WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; zh-Hans-CN; DBY2-W00 Build/HUAWEIDBY2-W00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 Quark/7.3.8.663 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"DBY2-W00\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 11.5 LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; HarmonyOS; BTK-AL09; HMSCore 6.14.0.322) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BTK-AL09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 11.5 S WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; HarmonyOS; TGR-W09; HMSCore 6.14.0.322; GMSCore 0.3.3.1.240913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 HuaweiBrowser/14.0.2.317 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"TGR-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad 11.5 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; HarmonyOS; BTK-W09; HMSCore 6.14.0.322; GMSCore 214816056) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BTK-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad C5 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; MON-W19 Build/HUAWEIMON-W19; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.111 Mobile Safari/537.36 [Pinterest/Android]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"MON-W19\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad Pro 11\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 12; GOT-AL09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 YaBrowser/23.5.5.60.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"GOT-AL09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad Pro 11 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; GOT-W09 Build/HUAWEIGOT-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Safari/537.36 T7/13.19 BDOS/1.0 (HarmonyOS 3.0.0) SP-engine/2.57.0 baiduboxapp/13.19.0.12 (Baidu; P1 12) NABar/1.0\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"GOT-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad Pro 12.6 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; WGR-W09 Build/HUAWEIWGR-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.105 Safari/537.36[FBAN/EMA;FBLC/en_US;FBAV/412.0.0.8.106;]\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"WGR-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad SE 11 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; HarmonyOS; AGS6-W09; HMSCore 6.12.2.309) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 HuaweiBrowser/11.1.5.315 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS6-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad Pro 13.2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; HarmonyOS; PCE-W29; HMSCore 6.14.0.322) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 HuaweiBrowser/15.0.4.312 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"PCE-W29\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad T 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; AGR-L09; HMSCore 5.0.4.301) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 HuaweiBrowser/11.0.3.304 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGR-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad T10s\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; zh-cn; AGS3-AL00 Build/HUAWEIAGS3-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/11.4 Mobile Safari/537.36 COVC/045530\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS3-AL00\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad T10s WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; AGS3-W09 Build/HUAWEIAGS3-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.93 Safari/537.36 OPR/60.0.2254.59405\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AGS3-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei MatePad T8 8 LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; KOB2K-L09 Build/HUAWEIKOB2K-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Safari/537.36 OPR/83.0.2254.73002\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"KOB2K-L09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei M3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; BTV-W09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BTV-W09\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 10 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0; BLA-L29 Build/HUAWEIBLA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3236.6 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BLA-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate X\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; TAH-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.111 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"TAH-AN00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate X2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; TET-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"TET-AN00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 X\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; EVR-L29 Build/HUAWEIEVR-L29; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"EVR-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LYA-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LYA-L09\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LYA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LYA-AL00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LYA-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LYA-AL10\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LYA-L0C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LYA-L0C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LYA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LYA-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LYA-TL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LYA-TL00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 50 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; DCO-LX9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"DCO-LX9\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P10 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; WAS-L03T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5199.205 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"WAS-L03T\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P20 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; ANE-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.143 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ANE-LX1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P20\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; EML-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"EML-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P20 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; CLT-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"CLT-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; ELE-L04) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.109 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ELE-L04\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; ELE-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ELE-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P30 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; VOG-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.143 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"VOG-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P40\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; ANA-AN00 Build/HUAWEIANA-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.26 SP-engine/2.22.0 baiduboxapp/11.26.0.10 (Baidu; P1 10) NABar/1.0\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ANA-AN00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P40 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; ELS-AN00 Build/HUAWEIELS-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 mailapp/6.0.0\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ELS-AN00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei 30 Pro+\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; EBG-AN10 Build/HUAWEIEBG-AN10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.86 Mobile Safari/537.36 EdgA/42.0.0.2741\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"EBG-AN10\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei 30S\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; CDY-AN90 Build/HUAWEICDY-AN90; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 mailapp/5.8.0\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"CDY-AN90\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; HUAWEI CAN-L13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5113.212 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"CAN-L13\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YAL-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YAL-L21\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YAL-L61) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YAL-L61\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YAL-L71) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YAL-L71\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YAL-L61D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YAL-L61D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YALE-L61A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YALE-L61A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YALE-L61D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YALE-L61D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Nova 5T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; YALE-L71A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"YALE-L71A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Enjoy10e\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 10; MED-AL00 Build/HUAWEIMED-AL00)\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"MED-AL00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y7 2018\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; LDN-L01) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.62 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"LDN-L01\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Honor 8X\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; JSN-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"JSN-L21\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y6 2019\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; MRD-LX1N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"MRD-LX1N\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y9 2019\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; JKM-LX2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"JKM-LX2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; AMN-LX3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"AMN-LX3\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y7p\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; ART-L28; HMSCore 6.8.0.311) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4476.0 HuaweiBrowser/12.1.2.312 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ART-L28\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y7p\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; ART-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.92 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"ART-L29\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Mate 20 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; SNE-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"SNE-LX1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei P10 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; WAS-LX1A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"WAS-LX1A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Y5 Lite 2018\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; DRA-LX5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"DRA-LX5\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Huawei Honor 8C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; BKK-LX2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Huawei\",\n            \"model\": \"BKK-LX2\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/imo.json",
    "content": "[\n    {\n        \"desc\": \"IMO FEEL A2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; IMO FEEL A2 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.105 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"IMO\",\n            \"model\": \"FEEL A2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"IMO Q2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; IMO Q2 Build/LMY47D; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/65.0.3325.109 Mobile Safari/537.36 GSA/7.22.24.21.arm\",\n        \"expect\": {\n            \"vendor\": \"IMO\",\n            \"model\": \"Q2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"IMO S2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; IMO S2 Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.162 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"IMO\",\n            \"model\": \"S2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"IMO Tab X9\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.3; id-id; IMO TAB X9 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"IMO\",\n            \"model\": \"TAB X9\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/infinix.json",
    "content": "[\n    {\n        \"desc\": \"Infinix Hot 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.0; en-us; Infinix HOT 4 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36 PHX/17.9\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"HOT 4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Hot 4 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Infinix_X556_LTE Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/390.0.0.27.105;]\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X556_LTE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Hot 7 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Infinix X625C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X625C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Hot 10T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Infinix X689C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X689C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Hot 11s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Infinix X6812 Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X6812\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Note 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Infinix_X601_LTE Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.111 Mobile Safari/537.36 GSA/11.5.9.21.arm64\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X601_LTE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Smart 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Infinix X657C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X657C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Infinix XPad\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Infinix X1101B Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.99 Safari/537.36 [FB_IAB/FB4A;FBAV/489.0.0.66.81;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X1101B\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Infinix Zero 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Infinix X6815B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Infinix\",\n            \"model\": \"X6815B\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/itel.json",
    "content": "[\n    {\n        \"desc\": \"itel A25\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; itel L5002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.130 Mobile Safari/537.36 OPR/63.3.3216.58675\",\n        \"expect\": {\n            \"vendor\": \"itel\",\n            \"model\": \"L5002\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"itel A50\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; itel A667L Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.103 Mobile Safari/537.36 OPR/83.1.2254.73239\",\n        \"expect\": {\n            \"vendor\": \"itel\",\n            \"model\": \"A667L\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"itel KidPad 1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Itel W7001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.101 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"itel\",\n            \"model\": \"W7001\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"itel Pad One\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; itel P10001L Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.172 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"itel\",\n            \"model\": \"P10001L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"itel RS4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; itel S666LN Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.165 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/468.1.0.56.78;]\",\n        \"expect\": {\n            \"vendor\": \"itel\",\n            \"model\": \"S666LN\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"itel Vision 2S\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; itel P651L Build/RP1A.201005.001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.76 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"itel\",\n            \"model\": \"P651L\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/jolla.json",
    "content": "[\n    {\n        \"desc\": \"Jolla\",\n        \"ua\": \"Mozilla/5.0 (Maemo; Linux; U; Jolla; Sailfish; Mobile; rv:31.0) Gecko/31.0 Firefox/31.0 SailfishBrowser/1.0\",\n        \"expect\": {\n            \"vendor\": \"Jolla\",\n            \"model\": \"undefined\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/kobo.json",
    "content": "[\n    {\n        \"desc\": \"Kobo eReader\",\n        \"ua\": \"Mozilla/5.0 (Unknown; Linux) AppleWebKit/538.1 (KHTML, like Gecko) Kobo eReader Safari/538.1\",\n        \"expect\": {\n            \"vendor\": \"Kobo\",\n            \"model\": \"eReader\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Kobo Touch\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/538.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/538.1 (Kobo Touch 0377/4.20.14622)\",\n        \"expect\": {\n            \"vendor\": \"Kobo\",\n            \"model\": \"Touch\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/lava.json",
    "content": "[\n    {\n        \"desc\": \"Lava Agni 2 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; LAVA LXX504 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.46 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/499.0.0.31.60;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LXX504\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Agni 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; LAVA LXX501 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.119 Mobile Safari/537.36[FBAN/EMA;FBLC/hi_IN;FBAV/396.0.0.9.115;]\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LXX501\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Blaze\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; en-US; LAVA Blaze Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.4.0.1306 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"Blaze\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Blaze 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; LAVA LZX409 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.97 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.47.36;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LZX409\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Blaze 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; LAVA LXX503) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LXX503\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Blaze Curve\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; LAVA LXX505 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.105 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/505.0.0.57.45;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LXX505\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Blaze Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; LAVA LZX404 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.50 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/503.0.0.69.76;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LZX404\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Iris 46\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LAVA LH9950) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/21.0 Chrome/110.0.5481.154 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LH9950\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Iris 54\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9; LAVA LH9931 Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 OPR/39.1.2254.136708\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LH9931\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava Storm 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; LAVA LXX508 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.100 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LXX508\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava V7 Prime\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LAVA LE9940) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LE9940\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lava V7s Prime\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9; LAVA LE9940_W Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 OPR/43.2.2254.140294\",\n        \"expect\": {\n            \"vendor\": \"LAVA\",\n            \"model\": \"LE9940_W\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/lenovo.json",
    "content": "[    \n    {\n        \"desc\": \"Lenovo A7\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9; en-US; Lenovo L19111 Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/13.2.8.1301 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L19111\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo A8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Lenovo L10041) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.73 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L10041\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo dtab Compact 42A\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; d-42A Build/SKQ1.220201.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.125 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"d-42A\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo IdeaTab A7-50\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Lenovo A3500-HV Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"A3500-HV\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo IdeaTab A2109A\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; ru-ru; A2109A Build/JDQ39; CyanogenMod-10.1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"A2109A\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo IdeaTab S6000\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; S6000 Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/55.0.2883.91 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"S6000\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo IdeaTab S6000\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; IdeaTab S6000-H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 YaBrowser/18.11.1.1011.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"IdeaTab S6000-H\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo K5 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9;zh-cn; Lenovo L38041 Build/PKQ1.190127.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.117 MobileLenovoBrowser/9.1.3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L38041\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo K9\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 8.1.0; en-US; Lenovo L38043 Build/O11019) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.4.8.1012 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L38043\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo K10 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo L39051) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.66 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L39051\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo K12\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Lenovo XT2081-4 Build/QCZ30.30-Q3-45-17; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/409.0.0.27.106;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"XT2081-4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo K12\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; Lenovo K12 Build/QOGS30.569-83-18; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.130 Mobile Safari/537.36 OPR/69.0.2254.66073\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"K12\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Legion 2 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Lenovo L70081 Build/RKQ1.201112.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.58 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L70081\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Legion Y90\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12;en-us; Lenovo L71061/SKQ1.211113.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.132 MobileLenovoBrowser/8.6.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L71061\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Legion Y700\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 13;zh-cn; Lenovo TB-9707F Build/TKQ1.221013.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.117 MobileLenovoBrowser/2.1.7 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-9707F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Legion Y700\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; TB320FC) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB320FC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Moto Tab\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; TB-X704A Build/NMF26F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X704A\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Phone\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Lenovo PB2-650M Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.105 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/311.0.0.44.117;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"PB2-650M\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo S5 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo L58041) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L58041\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Smart Tab M8\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 10; Lenovo TB-8505XS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 YaBrowser/21.11.7.71.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8505XS\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Smart Tab M8\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 10; Lenovo TB-8505FS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.166 YaBrowser/21.8.4.111.00 (beta) SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8505FS\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.1; Lenovo TAB 2 A7-30HC Build/LRX21M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.157 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TAB 2 A7-30HC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 2 A7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0.99; Lenovo TAB 2 A7-30DC Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.141 Safari/537.36 OPR/45.1.2246.125351\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TAB 2 A7-30DC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 2 A10\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.0.1; Lenovo TAB 2 A10-70L Build/LRX21M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.116 Safari/537.36 OPR/29.0.2254.120398\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TAB 2 A10-70L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 2 A10-30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; TB2-X30F Build/LenovoTB2-X30F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Mobile Safari/537.36 EdgA/90.0.818.49\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB2-X30F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Lenovo TB3-730X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB3-730X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 7 Essential\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; Lenovo TB3-710I Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/85.0.4183.127 Safari/537.36 GSA/5.4.28.19.arm\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB3-710I\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 7 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; en-US; Lenovo TB-7703X Build/S100) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.2.5.1102 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7703X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 8 Dual\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; 602LV Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/93.0.4577.82 Safari/537.36 GSA/12.36.22.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"602LV\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 8 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; zh-cn; Lenovo TB-8703F Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/9.8 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8703F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 8 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; Lenovo TB-8703X Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/65.0.3325.109 Safari/537.36 OPR/33.0.2254.125672\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8703X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 10 Business\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0; Lenovo TB3-X70F Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.111 Safari/537.36 OPR/32.0.2254.123747\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB3-X70F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 10 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0; Lenovo TB3-X70L Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/86.0.4240.185 Safari/537.36 OPR/52.1.2254.54298\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB3-X70L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 3 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Lenovo YT3-X90F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-X90F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; Lenovo TB-X304F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X304F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Lenovo TAB 2 A7-30HC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TAB 2 A7-30HC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; Lenovo TB-8504F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36 OPR/64.2.3282.60128\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8504F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 8.1.0; Lenovo TB-8504X Build/OPM1.171019.019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36 OPR/52.2.2254.54723\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8504X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 8 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 8.1.0; Lenovo TB-8704F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 YaApp_Android/21.21.0/apad YaSearchBrowser/21.21.0/apad BroPP/1.0 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8704F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 8 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; TB-8704V Build/OPM1.171019.019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/104.0.5112.97 Safari/537.36 [FB_IAB/FB4A;FBAV/380.0.0.29.109;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8704V\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 8 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 8.1.0; Lenovo TB-8704X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 YaBrowser/19.10.4.187.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8704X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 8 REL\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; Lenovo TB-8X04F Build/NMF26F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.100 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8X04F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 8.1.0; Lenovo TB-X304L Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.149 Safari/537.36 OPR/47.0.2254.146760\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X304L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 10 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 7.1.1; Lenovo TB-X704L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 YaBrowser/20.12.4.100.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X704L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 4 10 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 7.1.1; Lenovo TB-X704F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 YaBrowser/20.8.5.97.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X704F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; A101LV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"A101LV\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; Lenovo TB-7504X Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/119.0.6045.193 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/436.0.0.35.101;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7504X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 7 Essential\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.0; Lenovo TB-7304I Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Safari/537.36 OPR/54.0.2254.56148\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7304I\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 7 Essential\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; Lenovo TB-7304X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7304X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab 10 10.1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Lenovo TB-X103F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X103F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab E7\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 8.1.0; Lenovo TB-7104I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 BroPP/1.0 SA/3 Mobile Safari/537.36 YandexSearch/7.52/apad YandexSearchBrowser/7.52\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7104I\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab E8\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 7.0; Lenovo TB-8304F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.143 YaBrowser/19.7.4.97.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8304F1\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab K10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Lenovo TB-X6C6X Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X6C6X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab K10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Lenovo TB-X6C6F Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.83 Safari/537.36 [FB_IAB/FB4A;FBAV/488.0.0.78.79;IABMV/1;] FBNV/5\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X6C6F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab K11\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 10; Lenovo TB-J606N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 YaApp_Android/22.31.1/apad YaSearchBrowser/22.31.1/apad BroPP/1.0 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J606N\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab K11 Pro 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Lenovo TB-J607Z Build/SKQ1.211103.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.58 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J607Z\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo TB-7305X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 Mobile Safari/537.36 OPR/63.3.3216.58675\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7305X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M7\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 9; Lenovo TB-7305I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 YaApp_Android/20.85.0/apad YaSearchBrowser/20.85.0/apad BroPP/1.0 SA/1 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7305I\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M7 (Gen 3)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Lenovo TB-7306F Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.86 Safari/537.36 [FB_IAB/FB4A;FBAV/489.0.0.66.81;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7306F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M7 (Gen 3)\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 11; Lenovo TB-7306X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 YaBrowser/20.12.5.127.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-7306X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Lenovo TB-8505X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8505X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo TB-8505F Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36 GSA/10.82.8.21.arm64\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8505F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M8 (Gen 3)\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; zh-TW; Lenovo TB-8506X Build/RP1A.200720.011) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.4.0.1306 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8506X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M8 (Gen 4)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; TB300FU Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.86 Mobile Safari/537.36[FBAN/EMA;FBLC/en_US;FBAV/417.0.0.9.97;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB300FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M8 (Gen 4) (2024)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; TB301FU Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.170 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/472.0.0.45.79;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB301FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M8 FHD\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo TB-8705X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-8705X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; TB310FU) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB310FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Linux; 13; TB310XU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB310XU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 9; Lenovo TB-X606F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 YaBrowser/20.9.4.99.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X606F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Android 14; Mobile; Lenovo TB-X505F; rv:131.0) Gecko/131.0 Firefox/131.0\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X505F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Lenovo TB-X505L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6554.180 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X505L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo TB-X605F Build/PKQ1.190319.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Safari/537.36 [FB_IAB/FB4A;FBAV/298.0.0.46.116;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X605F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; Lenovo TB-X505X Build/QKQ1.191224.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.138 Safari/537.36 OPR/52.2.2254.54723\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X505X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 (Gen 3) \",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; TB328XU Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.58 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB328XU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 (Gen 3) \",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; TB328FU Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.57 Safari/537.36 [FB_IAB/FB4A;FBAV/418.0.0.33.69;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB328FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 FHD\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; Lenovo TB-X605FC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6481.193 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X605FC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 FHD\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo TB-X605LC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X605LC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 FHD\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 9; Lenovo TB-X605L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 YaBrowser/20.12.0.141.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X605L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 FHD Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; Lenovo TB-X606F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6496.93 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X606F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 FHD Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo TB-X606FA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5813.205 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X606FA\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 FHD Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Lenovo TB-X606X Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X606X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 HD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; it-it; Lenovo TB-X306F Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36 PHX/6.2\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X306F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 HD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; it-it; Lenovo TB-X306F Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36 PHX/6.2\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X306F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M10 Plus (Gen 3)\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; Lenovo TB-X306X Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.210 Safari/537.36 OPR/55.1.2254.56965\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X306X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab M11\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; TB330FU Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.60 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB330FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P10\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 9; Lenovo TB-X705L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 YaBrowser/21.3.3.160.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-X705L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; Lenovo TB-J606L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.2311.135 YaBrowser/21.11.5.121.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J606L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; zh-cn; Lenovo TB-J606F Build/RKQ1.210303.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/12.1 Mobile Safari/537.36 COVC/045830\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J606F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Lenovo TB-J616X Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Safari/537.36 [FB_IAB/FB4A;FBAV/418.0.0.33.69;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J616X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11 (Gen 2)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; TB350FU Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.46 Safari/537.36 [FB_IAB/FB4A;FBAV/490.0.0.63.82;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB350FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Lenovo TB-J616F Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.9 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J616F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; zh-CN; Lenovo TB-J706F Build/RKQ1.201112.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.8.6.223 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J706F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Lenovo TB-J706L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 EdgA/103.0.1264.71\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J706L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P11 Pro (Gen 2)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; TB132FU Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB132FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P12\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; TB370FU Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.106 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB370FU\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P12 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; Lenovo TB-Q706F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-Q706F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab P12 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; Lenovo TB-Q706Z Build/TKQ1.221013.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.103 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-Q706Z\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab QT K11 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 12; Lenovo TB-J6C6F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.114 YaBrowser/22.9.3.82.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J6C6F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab QT K11 Pro WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Lenovo TB-J607F Build/RKQ1.201217.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.86 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"TB-J607F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab V7\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9; en-US; Lenovo PB-6505M Build/PKQ1) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.9.9.1155 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"PB-6505M\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Tab V7\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 9; Lenovo PB-6505Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 YaBrowser/20.9.3.85.00 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"PB-6505Y\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo X3 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Lenovo X3 Lite) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.88 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"X3 Lite\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Smart Tab\",\n        \"ua\": \"Mozilla/5.0 (Android 11; Mobile; Lenovo YT-X705X; rv:129.0) Gecko/129.0 Firefox/129.0\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT-X705X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Smart Tab\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 10; Lenovo YT-X705F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 YaBrowser/20.2.4.153.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT-X705F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Smart Tab\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Lenovo YT-X705L Build/PKQ1.181218.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Safari/537.36 GSA/11.38.8.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT-X705L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; Lenovo YT3-X50L Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.149 Safari/537.36 OPR/46.0.2254.145391\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-X50L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; Lenovo YT3-X50L Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.149 Safari/537.36 OPR/46.0.2254.145391\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-X50L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Lenovo YT3-X50M Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-X50M\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3 8\",\n        \"ua\": \"Mozilla/5.0(Linux; U; Android 5.1.1; pt-BR; Lenovo YT3-850F Build/LMY47V) AppleWebKit/537.36(KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-850F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3 8\",\n        \"ua\": \"Mozilla/5.0(Linux; U; Android 5.1.1; lv-LV; Lenovo YT3-850L Build/LMY47V) AppleWebKit/537.36(KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-850L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3 10\",\n        \"ua\": \"Mozilla/5.0(Linux; U; Android 5.1.1; vi-VN; Lenovo YT3-850M Build/LMY47V) AppleWebKit/537.36(KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT3-850M\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; Lenovo YT-X703L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 OPR/64.2.3282.60128\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT-X703L\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 3 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.2; YT-X703F Build/NJH47F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.141 Safari/537.36 OPR/45.0.2246.125120\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT-X703F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tab 11\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 12; Lenovo YT-J706X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.42 YaBrowser/24.1.1.42.01 (beta) Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"YT-J706X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.2; ru-ru; Lenovo B6000; Android/4.4.2; Release/08.26.2015) AppleWebKit/534.30 (KHTML, like Gecko) Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B6000\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Lenovo B6000-H Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 GSA/7.24.32.16.arm\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B6000-H\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; es-us; Lenovo B6000-F/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.2.2 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B6000-F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; ru-ru; Lenovo B8000-F Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B8000-F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 10\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; ru-ru; Lenovo B8000-H Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30 Mobile UCBrowser/3.4.3.532\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B8000-H\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 10 HD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.2; en-US; Lenovo B8080-H Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.0.0.1088 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B8080-H\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Yoga Tablet 10 HD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.3; ru-ru; Lenovo B8080-F/JLS36C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.3 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"B8080-F\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Lenovo Z6\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 9;zh-cn; Lenovo L78121 Build/PKQ1.190319.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.117 MobileLenovoBrowser/9.1.3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Lenovo\",\n            \"model\": \"L78121\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/lg.json",
    "content": "[\n    {\n        \"desc\": \"LG V40 ThinQ\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LM-V405) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-V405\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG K30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; LM-X410.F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-X410.F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG K30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LM-X410.FGN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-X410.FGN\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG K40\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; LM-X420) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.57 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-X420\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Stylo 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; LM-Q710(FGN)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.57 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"undefined\",\n            \"model\": \"LM-Q710(FGN)\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Stylo 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LM-Q720) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-Q720\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG G7 ThinQ\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; LM-G710VM Build/PKQ1.181105.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-G710VM\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG K20\",\n        \"ua\": \"Mozilla/5.0 (Android 13; Mobile; LG-M255; rv:111.0) Gecko/111.0 Firefox/111.0\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"M255\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG K500\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; LG-K500 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"K500\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Nexus 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.1; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"Nexus 4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Nexus 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.3; en-us; Google Nexus 4 - 4.3 - API 18 - 768x1280 Build/JLS36G) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"Nexus 4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Nexus 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"Nexus 5\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Wing\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; LM-F100N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.101 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LM-F100N\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"LG Smart TV\",\n        \"ua\": \"Mozilla/5.0 (DirectFB; U; Linux mips; en) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) LG Browser (; LG NetCast.TV-2011)\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"LG Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; NetCast; U) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/53.0.2785 34 Safari/537.31 SmartTV/8.5\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"LG Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen Safari/537.41 LG Browser/7.00.00(LGE; 42LB670V-ZA; 05.05.90; 1); webOS.TV-2014; LG NetCast.TV-2013 Compatible (LGE, 42LB670V-ZA, wireless)\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"42LB670V-ZA\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"LG Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/53.0.2785.34 Safari/537.36 LG Browser/8.00.00(LGE; 32LM627BPSB; 05.40.45; 1; DTV_W19R); webOS.TV-2019; LG NetCast.TV-2013 Compatible (LGE, 32LM627BPSB, wireless)\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"32LM627BPSB\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"LG Smart TV\",\n        \"ua\": \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 HbbTV/1.3.1 ( DRM; LGE; OLED55B7V_Z; WEBOS3.5 06.10.60; W3_M16P; ) FVC/2.0 (LGE; WEBOS3.5 ;)\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"OLED55B7V_Z\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"LG Android TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; LG Android TV Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"LG VK Series Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.2; VK700 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.84 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"VK700\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"LG LK Series Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.1; LGLK430 Build/LRX21Y) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LK430\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"LG G Pad F2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; LG-LK460 Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"LK460\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"LG Watch Urbane\",\n        \"ua\": \"Mozilla/5.0 Linux; Android 7.1.1; LG Watch Urbane Build/NWD1.180306.004 AppleWebKit/537.36 KHTML, like Gecko Chrome/19.77.34.5 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"Watch Urbane\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"LG G Watch R\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; G Watch R Build/LCA44B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Crosswalk/15.44.384.12 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"LG\",\n            \"model\": \"G Watch R\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/logitech.json",
    "content": "[\n    {\n        \"desc\": \"Logitech\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 11; GR0006 Build/SQ02K.00.0018)\",\n        \"expect\": {\n            \"vendor\": \"Logitech\",\n            \"model\": \"GR0006\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/meizu.json",
    "content": "[\n    {\n        \"desc\": \"Meizu M5 Note\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; M5 Note Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043024 Safari/537.36 MicroMessenger/6.5.7.1040 NetType/WIFI Language/zh_CN\",\n        \"expect\": {\n            \"vendor\": \"Meizu\",\n            \"model\": \"M5 Note\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Meizu M3S\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux; Android 5.1; MZ-M3s Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrom/45.0.2454.94 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Meizu\",\n            \"model\": \"M3s\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/micromax.json",
    "content": "[\n\n    {\n        \"desc\": \"Micromax Bharat 2 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.0; en-US; Micromax Q402Plus Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.12.9.1226 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Micromax\",\n            \"model\": \"Q402Plus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Micromax Canvas Infinity\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.1.2; en-US; Micromax HS2 Build/N2G47H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/13.2.0.1296 (SpeedMode) U4/1.0 UCWEB/2.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Micromax\",\n            \"model\": \"HS2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Micromax In 1b\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; Micromax E7533 Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36 OPR/54.0.2254.56148\",\n        \"expect\": {\n            \"vendor\": \"Micromax\",\n            \"model\": \"E7533\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/microsoft.json",
    "content": "[\n    {\n        \"desc\": \"Microsoft Lumia 950\",\n        \"ua\": \"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586\",\n        \"expect\": {\n            \"vendor\": \"Microsoft\",\n            \"model\": \"Lumia 950\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Microsoft Surface Duo\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 10; Surface Duo Build/2020.1014.61)\",\n        \"expect\": {\n            \"vendor\": \"Microsoft\",\n            \"model\": \"Surface Duo\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Microsoft Lumia 950\",\n        \"ua\": \"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586\",\n        \"expect\": {\n            \"vendor\": \"Microsoft\",\n            \"model\": \"Lumia 950\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xbox\",\n        \"ua\": \"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; Xbox)\",\n        \"expect\": {\n            \"vendor\": \"Microsoft\",\n            \"model\": \"Xbox\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Xbox One\",\n        \"ua\": \"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; Xbox; Xbox One)\",\n        \"expect\": {\n            \"vendor\": \"Microsoft\",\n            \"model\": \"Xbox One\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/motorola.json",
    "content": "[\n    {\n        \"desc\": \"Motorola Defy XT\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; XT555C Build/V1.67D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT555C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Droid RAZR 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 2.3; xx-xx; DROID RAZR 4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"DROID RAZR 4G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Edge 30 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; XT2201-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2201-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Edge 30 Ultra\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; motorola edge 30 ultra Build/U1SQS34.52-21-1-13; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 M\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"edge 30 ultra\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Edge 40\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; motorola edge 40 Build/U1TL34.115-16-1-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.104 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"edge 40\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Edge X30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; XT2201-2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.59 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2201-2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola RAZR 2019\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; motorola razr) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.1 Chrome/75.0.3770.143 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"razr\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto 360\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4; Moto 360 Build/KNX01S) AppleWebKit/537.36 (KHTML, like Gecko) WIB/0.9.8 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"Moto 360\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto E\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; Moto E (4) Build/NDQS26.69-64-11-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"Moto E (4)\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto E6s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; MOTOROLA E6S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"E6S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto E7 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; moto e(7) plus Build/QPZS30.30-Q3-38-69-12; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.14 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto e(7) plus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto E7 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; XT2081-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.171 Mobile Safari/537.36 OPR/102.0.4864.0\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2081-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto G 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; moto g 5G - 2023 Build/U1TPNS34.26-48-2-7; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36 EdgA/124.0.2478.64\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto g 5G - 2023\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto G 5G (2022)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; moto g 5G (2022) Build/S1SAS32.47-77-9; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.116 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/402.0.0.11.101;]\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto g 5G (2022)\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto g(6) Play\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; moto g(6) play) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto g(6) play\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto g(7) Supra\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; moto g(7) supra Build/PCOS29.114-134-2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/73.0.3683.90 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto g(7) supra\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto G10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; XT2127-2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2127-2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto G24 Power\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; moto g24 power Build/UTAS34.82-97-1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.138 Mobile Safari/537.36 OPR/89.0.2254.76420\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto g24 power\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto G30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; XT2129-3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2129-3\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto G54 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; moto g54 5G Build/U1TDS34.94-12-9-10-2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.122 Mobile Safari/537.36 OPX/2\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto g54 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto X\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.4; XT1097 Build/KXE21.187-38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT1097\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto X\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT1058\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto X Force\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.0; XT1580 Build/NPKS25.200-12-9; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/65.0.3325.109 Mobile Safari/537.36 OPR/32.0.2254.123747\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT1580\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto S30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; XT2243-2 Build/T1SJC33.51-19-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36 T7/13.30 SP-engine/2.53.0 matrixstyle/0 lite baiduboxapp/6.2.0.10 (Baidu; P1 13) NABar/1.0\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2243-2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto X30 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 13; zh-CN; XT2241-1 Build/T1SQ33.111-12-19) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/16.1.3.1264 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2241-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto Z3 Play\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Moto Z3 Play) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"Moto Z3 Play\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Moto Z4\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; moto z4 Build/QDF30.130-42-5-17; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 OPR/2.3.0\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"moto z4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Nexus 6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"Nexus 6\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola One 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; motorola one 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"one 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola P30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; XT1943-1 Build/OPM1.171019.019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36 T7/13.50 SP-engine/2.88.0 baiduboxapp/13.50.5.10 (Baidu; P1 8.1.0) NABar/1.0\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT1943-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Razr 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; motorola razr 5G Build/S2PS32.57-23-21; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.97 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/497.0.0.47.36;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"razr 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Razr 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; XT2071-4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"XT2071-4\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Motorola Razr 50 Ultra\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; motorola razr 50 ultra Build/U3UX34.56-29-2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.260 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Motorola\",\n            \"model\": \"razr 50 ultra\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/nintendo.json",
    "content": "[\n    {\n        \"desc\": \"Nintendo Switch\",\n        \"ua\": \"Mozilla/5.0 (Nintendo Switch; WifiWebAuthApplet) AppleWebKit/606.4 (KHTML, like Gecko) NF/6.0.1.15.4 NintendoBrowser/5.1.0.20393\",\n        \"expect\": {\n            \"vendor\": \"Nintendo\",\n            \"model\": \"Switch\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Nintendo WiiU\",\n        \"ua\": \"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.4.2.9 NintendoBrowser/4.2.0.11146.EU\",\n        \"expect\": {\n            \"vendor\": \"Nintendo\",\n            \"model\": \"WiiU\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Nintendo Wii\",\n        \"ua\": \"Opera/9.10 (Nintendo Wii; U; ; 1621; en)\",\n        \"expect\": {\n            \"vendor\": \"Nintendo\",\n            \"model\": \"Wii\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Nintendo 3DS\",\n        \"ua\": \"Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7610.EU\",\n        \"expect\": {\n            \"vendor\": \"Nintendo\",\n            \"model\": \"3DS\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Nintendo 3DS\",\n        \"ua\": \"Mozilla/5.0 (New Nintendo 3DS like iPhone) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.0.5.15 Mobile NintendoBrowser/1.3.10126.EU\",\n        \"expect\": {\n            \"vendor\": \"Nintendo\",\n            \"model\": \"3DS\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/nokia.json",
    "content": "[\n    {\n        \"desc\": \"Nokia 1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Nokia 1 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.15 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia3xx\",\n        \"ua\": \"Nokia303/14.87 CLDC-1.1\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"303\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia 3.2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Nokia 3.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"3.2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia 5800 XpressMusic\",\n        \"ua\": \"Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Nokia5800d-1/10.4.016; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"5800d-1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Nokia 7.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"7.2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia 808 PureView\",\n        \"ua\": \"Mozilla/5.0 (Symbian; U; Nokia808 PureView; en-GB) AppleWebKit/534.3 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Mobile Safari/534.3\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"808 PureView\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia 808 PureView\",\n        \"ua\": \"Mozilla/5.0 (Symbian/3; Series60/5.5 Nokia808PureView/113.010.1508; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/535.1 (KHTML, like Gecko) NokiaBrowser/8.3.2.21 Mobile Safari/535.1 3gpp-gba\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"808PureView\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia Lumia 630\",\n        \"ua\": \"UCWEB/2.0 (Windows; U; wds 8.10; en-IN; NOKIA; RM-978_1046) U2/1.0.0 UCBrowser/4.2.0.524 U2/1.0.0 Mobile\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"RM-978\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia N9\",\n        \"ua\": \"Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"N9\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia N900\",\n        \"ua\": \"Mozilla/5.0 (Linux; Maemo 5.0; Nokia N900; Build/4.0.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"N900\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nokia T20\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Nokia T20) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"T20\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Nokia T20\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Nokia T20 Build/RP1A.201005.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/93.0.4577.62 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"T20\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Nokia T21\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 13; Nokia T21 Build/TP1A.220624.014)\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"T21\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Nokia 2720 Flip\",\n        \"ua\": \"Mozilla/5.0 (Mobile; Nokia_2720_Flip; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5.2\",\n        \"expect\": {\n            \"vendor\": \"Nokia\",\n            \"model\": \"2720 Flip\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/nothing.json",
    "content": "[\n    {\n        \"desc\": \"Nothing 1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; A063) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/22.0 Chrome/111.0.5563.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"A063\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nothing 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; A065 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.53 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"A065\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nothing 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; AIN065 Build/AQ3A.240929.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.90 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/496.0.0.45.65;IABMV/1;] FBNV/500\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"AIN065\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nothing 2a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; A142 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.71 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"A142\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nothing 2a Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; A142P Build/UP1A.231005.007) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.107 Mobile Safari/537.36 OPX/2.6\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"A142P\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nothing 3a\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; A059 Build/AQ3A.241015.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.103 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"A059\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Nothing 3a Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; A059P Build/AQ3A.241015.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/136.0.7103.57 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/511.0.0.73.36;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Nothing\",\n            \"model\": \"A059P\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/nvidia.json",
    "content": "[\n    {\n        \"desc\": \"Tegra Note 7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; TegraNote-P1640 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nvidia\",\n            \"model\": \"TegraNote-P1640\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Nvidia Shield\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; SHIELD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nvidia\",\n            \"model\": \"SHIELD\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Nvidia Shield Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; SHIELD Tablet Build/LVY48E; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.19 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nvidia\",\n            \"model\": \"SHIELD Tablet\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Nvidia Shield Tablet K1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; SHIELD Tablet K1 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Nvidia\",\n            \"model\": \"SHIELD Tablet K1\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Nvidia Shield TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; SHIELD Android TV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36  \",\n        \"expect\": {\n            \"vendor\": \"Nvidia\",\n            \"model\": \"SHIELD Android TV\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/oneplus.json",
    "content": "[\n    {\n        \"desc\": \"OnePlus One\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.4; A0001 Build/KTU84Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"A0001\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus One\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; OnePlus One A0001 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"A0001\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; ONE A2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"A2003\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; ONEPLUS A3000 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"A3000\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; ONEPLUS A6003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.89 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"A6003\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 6T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; ONEPLUS A6010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"A6010\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 7T Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.57 Mobile Safari/537.36 EdgA/110.0.1587.66\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"HD1913\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 8 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; OnePlus 8 Lite) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4741.47 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"8 Lite\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 8 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; IN2025) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.119 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"IN2025\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 8T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"KB2005\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 9\",\n        \"ua\": \"Mozilla/5.0 (Android 14; SDK 28; OnePlus 9) Gecko/128.0 Firefox/128.0\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"9\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 9\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; LE2113 Build/TP1A.220905.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36 Flipboard/4.3.14/5377,4.3.14.5377\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"LE2113\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 9 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; LE2123) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.128 Mobile Safari/537.36 OPR/73.0.3832.69371\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"LE2123\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 9R\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; LE2100) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 YaApp_Android/21.114.1 YaSearchBrowser/21.114.1 BroPP/1.0 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"LE2100\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 9RT 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; en-in; MT2111 Build/RKQ1.210614.002) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 GSA/13.14.15.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"MT2111\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 10 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 12; NE2213) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.148 YaBrowser/22.7.5.90.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"NE2213\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 10RT\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; CPH2413) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"CPH2413\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 11R\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; CPH2487) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"CPH2487\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 13\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; CPH2653 Build/AP3A.240617.008; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.92 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/504.0.0.69.64;IABMV/1;] FBNV/5\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"CPH2653\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus 15\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 16; PLK110 Build/BP2A.250605.015; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.135 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PLK110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; zh-cn; PGKM10 Build/AP3A.240617.008) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.168 Mobile Safari/537.36 HeyTapBrowser/40.9.6.2\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PGKM10\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; zh-CN; PHK110 Build/UKQ1.231108.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.3.6.1367 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PHK110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 2 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 13; PJA110) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 YaBrowser/23.1.0.284.00 (beta) SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PJA110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 2V\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; zh-cn; PHP110 Build/AP3A.240617.008) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/121.0.6167.71 MQQBrowser/16.3 Mobile Safari/537.36 COVC/047707\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PHP110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; zh-CN; PJE110 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.80 Quark/7.9.7.782 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PJE110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 3 Pro 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; zh-CN; PJX110 Build/UKQ1.231108.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.80 Quark/7.11.4.814 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PJX110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 3V\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; zh-cn; PJF110 Build/UP1A.231005.007) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/90.0.4430.61 Mobile Safari/537.36 HeyTapBrowser/40.8.33.1.2beta\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PJF110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; zh-cn; PKG110 Build/UKQ1.231108.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.168 Mobile Safari/537.36 HeyTapBrowser/40.9.9.2\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PKG110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; zh-CN; PGP110 Build/UKQ1.230924.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.2.9.1360 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PGP110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Ace Racing Edition\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 13; zh-CN; PGZ110 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.3.6.1367 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"PGZ110\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Nord CE 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; CPH2613) AppleWebKit/537.36 (KHTML, like Gecko) JioSphere/5.0.4 Chrome/119.0.6045.193 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"CPH2613\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Nord N10 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; BE2029) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.185 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"BE2029\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Nord N30 SE 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; CPH2605 Build/TP1A.220905.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.7049.92 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/509.0.0.67.28;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"CPH2605\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Nord N100\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; BE2015 Build/QKQ1.200719.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"BE2015\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Open\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 15; CPH2551 Build/AP3A.240617.008)\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"CPH2551\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Pad Go 11.35\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 14; OPD2304) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.629 YaApp_Android/24.101/apad YaSearchBrowser/24.101/apad BroPP/1.0 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"OPD2304\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Pad 2 12.1 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; OPD2403 Build/UKQ1.231108.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"OPD2403\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Pad 11.61 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; OPD2203 Build/UKQ1.230924.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"OPD2203\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"OnePlus Watch 2\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 13; OPWWE231 Build/TWR7.231113.001.OPWWE231_11_A.117.240703)\",\n        \"expect\": {\n            \"vendor\": \"OnePlus\",\n            \"model\": \"OPWWE231\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/oppo.json",
    "content": "[\n    {\n        \"desc\": \"OPPO Pad\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 13; zh-CN; OPD2101 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/16.3.9.1290 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"OPD2101\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Neo\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; R831T Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 OppoBrowser/3.3.2 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"R831T\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO R7s\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"R7s\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO A3s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; CPH1803 Build/OPM1.171019.026; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"CPH1803\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO A12\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; CPH2083) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"CPH2083\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Reno\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; PCAT00 Build/PKQ1.190101.001; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"PCAT00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Reno3 Pro 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; PCLM50) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.117 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"PCLM50\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Reno4 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; xx-xx; PEAM00 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"PEAM00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Reno4 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; PDPM00 Build/QKQ1.200216.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"PDPM00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Reno4 Pro 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; xx-xx; PDNT00 Build/QKQ1.200216.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"PDNT00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Reno5 A\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; A101OP) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"A101OP\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Find X\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; PAFM00 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"PAFM00\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Find 7a\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.3; xx-xx; X9007 Build/JLS36C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"X9007\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO F5\",\n        \"ua\": \"ozilla/5.0 (Linux; Android 7.1.1; CPH1723) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"CPH1723\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Watch 46mm\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; OW19W3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"OW19W3\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Watch 41mm\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; OW19W2 Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"OW19W2\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Watch 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; OW20W1 Build/OPM1.171019.026.11_A.37.210713172937; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"OW20W1\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"OPPO Watch X\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 13; OWWE231 Build/TWR7.231113.001.OWWE231_11_A.117.240703)\",\n        \"expect\": {\n            \"vendor\": \"OPPO\",\n            \"model\": \"OWWE231\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/ouya.json",
    "content": "[\n    {\n        \"desc\": \"Ouya\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.1.2; OUYA Console Build/JZO54L-OUYA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"OUYA\",\n            \"model\": \"undefined\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/panasonic.json",
    "content": "[\n    {\n        \"desc\": \"Panasonic T31\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; Panasonic T31 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.170 Mobile Safari/537.36 \",\n        \"expect\": {\n            \"vendor\": \"Panasonic\",\n            \"model\": \"T31\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Panasonic TX-32CSW514 SmartTV\",\n        \"ua\": \"HbbTV/1.2.1 (;Panasonic;VIERA 2015;3.014;a001-003 4000-0000;)\",\n        \"expect\": {\n            \"vendor\": \"Panasonic\",\n            \"model\": \"VIERA 2015\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Panasonic TX-40FXW724 SmartTV\",\n        \"ua\": \"HbbTV/1.4.1 (+DRM;Panasonic;SmartTV2018mid;3.024;4301-0003 0002-0000;SmartTV2018;)\",\n        \"expect\": {\n            \"vendor\": \"Panasonic\",\n            \"model\": \"SmartTV2018mid\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Panasonic TX-43HXW904 SmartTV\",\n        \"ua\": \"HbbTV/1.5.1 (+DRM;Panasonic;SmartTV2020mid;3.326;4301-0003 0008-0000;com.panasonic.SmartTV2020mid;)\",\n        \"expect\": {\n            \"vendor\": \"Panasonic\",\n            \"model\": \"SmartTV2020mid\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Panasonic DMR-HST130 SAT receiver\",\n        \"ua\": \"HbbTV/1.1.1 (+PVR;Panasonic;DIGA WebKit M8658;3.420;;)\",\n        \"expect\": {\n            \"vendor\": \"Panasonic\",\n            \"model\": \"DIGA WebKit M8658\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/philips.json",
    "content": "[\n    {\n        \"desc\": \"Philips S616\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; Philips S616 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"S616\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Philips W8510\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; Philips W8510 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.68 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"W8510\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Philips SmartTV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; PHILIPS 4k TV Build/RTXC.231010.082.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.71 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"PHILIPS\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Philips SmartTV\",\n        \"ua\": \"Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Philips 32PFL6606K/02 SmartTV (2011)\",\n        \"ua\": \"Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.1.0; en) Presto/2.6.33 Version/10.70\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Philips 32PFL6606K/02 SmartTV (2013)\",\n        \"ua\": \"Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.1.0; en) Presto/2.6.33 Version/10.70\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Philips 32PHS5301/12 SmartTV (2016)\",\n        \"ua\": \"Mozilla/5.0 (Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36 OPR/29.0.1803.0 OMI/4.5.23.37.MOT2.13 HbbTV/1.2.1 (;Philips;32PHS5301/12;;_TV_MT5800;) Firmware/TPM161E_012.002.045.001 en\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"32PHS5301/12\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Philips PH0M_EA_T32\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Philips FHD Android TV Build/QTG3.201102.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.186 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Philips PH3M_AL_T32\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Philips Google TV TA7 Build/RTM5.220609.199; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.58 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Philips\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/pico.json",
    "content": "[\n    {\n        \"desc\": \"Pico 4\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.8.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.38 Chrome/105.0.5195.68 VR Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"PICO\",\n            \"model\": \"4\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Pico 4\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36 OculusBrowser/7.0\",\n        \"expect\": {\n            \"vendor\": \"PICO\",\n            \"model\": \"4\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Pico Neo3 Link\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Pico Neo3 Link OS5.8.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Pico\",\n            \"model\": \"Neo3 Link\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Pico Neo 3\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Pico Neo 3 OS5.12.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.48 Chrome/105.0.5195.68 VR Safari/537.36  OculusBrowser/7.0\",\n        \"expect\": {\n            \"vendor\": \"Pico\",\n            \"model\": \"Neo 3\",\n            \"type\": \"xr\"\n        }\n    },\n    {\n        \"desc\": \"Pico Neo 3 Pro\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Pico Neo 3 Pro OS5.9.9.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.46 Chrome/105.0.5195.68 VR Safari/537.36  OculusBrowser/7.0\",\n        \"expect\": {\n            \"vendor\": \"Pico\",\n            \"model\": \"Neo 3 Pro\",\n            \"type\": \"xr\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/polytron.json",
    "content": "[\n    {\n        \"desc\": \"Polytron Prime 7 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 7.0; POLYTRON_P552 Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 OPR/50.0.2254.149182\",\n        \"expect\": {\n            \"vendor\": \"POLYTRON\",\n            \"model\": \"P552\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Polytron Rocket T1\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.0; en-US; POLYTRON R2501 Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/13.1.2.1293 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"POLYTRON\",\n            \"model\": \"R2501\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Polytron Rocket T6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; POLYTRON R2509) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.92 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"POLYTRON\",\n            \"model\": \"R2509\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Polytron Zap 6 Posh\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.1; in-ID; POLYTRON_4G501 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.10.0.1163 UCTurbo/1.9.9.900 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"POLYTRON\",\n            \"model\": \"4G501\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/realme.json",
    "content": "[\n    {\n        \"desc\": \"Realme C1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; RMX1811 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX1811\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme C2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; RMX1941) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX1941\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme Narzo 20\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 10; xx-xx; RMX2193 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX2193\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme 2 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; RMX1801) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX1801\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme 3 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; RMX1851) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX1851\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; RMX3085) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX3085\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme 9 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; RMX3471) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX3471\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Realme GT Master\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; RMX3363) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Realme\",\n            \"model\": \"RMX3363\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/retroid.json",
    "content": "[\n    {\n        \"desc\": \"Retroid Pocket 4 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 13; Retroid Pocket 4 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.96 YaBrowser/24.4.3.96.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Retroid\",\n            \"model\": \"Pocket 4 Pro\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/roku.json",
    "content": "[\n    {\n        \"desc\": \"Roku\",\n        \"ua\": \"Mozilla/5.0 (Roku) AppleWebKit/537.36 (KHTML, like Gecko) Web/1.1 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Roku\",\n            \"model\": \"\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Roku\",\n        \"ua\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36 Roku/DVP-8.10 (468.10E04145A)\",\n        \"expect\": {\n            \"vendor\": \"Roku\",\n            \"model\": \"DVP-8.10\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Roku\",\n        \"ua\": \"Roku4640X/DVP-7.70 (297.70E04154A)\",\n        \"expect\": {\n            \"vendor\": \"Roku\",\n            \"model\": \"DVP-7.70\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/samsung.json",
    "content": "[\n    {\n        \"desc\": \"Samsung Galaxy A21s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.0 Chrome/75.0.3770.143 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-A217F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy A31\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SM-A315G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-A315G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy A50\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.105 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-A505F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy A50s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; SM-A507FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-A507FN\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy A52s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; SM-A528B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-A528B\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy A80\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SM-A805F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.112 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-A805F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Fold\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-F900U Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.2 Chrome/67.0.3396.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-F900U\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Z Flip\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SM-F700N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-F700N\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Z Fold2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SM-F916B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-F916B\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy S10E\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SM-G970F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-G970F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy S20 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SCG01) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SCG01\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Note 10+\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SM-N976V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.89 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-N976V\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SM-C5000\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; SM-C5000 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36 wkbrowser 4.1.35 3065\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-C5000\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung C8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; SM-C7108) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-C7108\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Note 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; GT-N5100 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"GT-N5100\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SM-T231\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; SM-T231 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-T231\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab 6 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-P610) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/12.0 Chrome/79.0.3945.136 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-P610\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab A 9.7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; SM-P550 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.90 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-P550\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab A 10.1\",\n        \"ua\": \" Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-T515) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/13.0 Chrome/83.0.4103.106 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-T515\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab S7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-T870\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab S8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; SM-X706B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-X706B\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab S\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; SM-T700 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-T700\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Tab Pro 10.1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; SM-T520 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-T520\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Watch\",\n        \"ua\": \"Mozilla/5.0 (Linux; Tizen 5.5; SAMSUNG SM-R805W) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.0 Chrome/69.0.3497.106 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-R805W\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Watch Active 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Tizen 5.5; SAMSUNG SM-R820) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.0 Chrome/69.0.3497.106 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-R820\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Watch4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-R875U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.2. Chrome/102.0.5005.125 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-R875U\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Watch5 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-R925U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2. Chrome/111.0.5563.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-R925U\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Watch7\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 14; SM-L300 Build/AW2E.240318.016)\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-L300\",\n            \"type\": \"wearable\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Note 10.1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; SM-P605) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-P605\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV2011\",\n        \"ua\": \"HbbTV/1.1.1 (;;;;;) Maple;2011\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SmartTV2011\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV2012\",\n        \"ua\": \"HbbTV/1.1.1 (;Samsung;SmartTV2012;;;) WebKit\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SmartTV2012\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV2014\",\n        \"ua\": \"HbbTV/1.1.1 (;Samsung;SmartTV2014;T-NT14UDEUC-1060.4;;) WebKit\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SmartTV2014\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV\",\n        \"ua\": \"Mozilla/5.0 (SMART-TV; Linux; Tizen 2.3) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.0 TV Safari/538.1\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV\",\n        \"ua\": \"Mozilla/5.0 (SMART-TV; Linux; Tizen 8.0) AppleWebKit/537.36 (KHTML, like Gecko) Samsung Browser/7.0 Chrome/108.0.5359.1 TV Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"undefined\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Samsung SmartTV HBBTV\",\n        \"ua\": \"HbbTV/1.5.1 (+DRM;Samsung;SmartTV2021:UAU7000;T-KSU2EDEUC-1506.0;KantSU2e;urn:samsungtv:familyname:21_KANTSU2E_UHD_BASIC:2021;) Tizen/6.0 (+TVPLUS+SmartHubLink) Chrome/76 LaTivu_1.0.1_2021 RVID/17\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SmartTV2021:UAU7000\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Galaxy Nexus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"Galaxy Nexus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy C9 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; SAMSUNG SM-C900F Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.2 Chrome/44.0.2403.133 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-C900F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy S5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0; SM-G900F Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-G900F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy J7 Prime\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; SM-G610F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-G610F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy S6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; SM-G920I Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-G920I\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy S6 Edge\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; SM-G925I Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-G925I\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Note 5 Chrome\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; SM-N920C Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.91 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-N920C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Note 5 Samsung Browser\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-N920C Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"SM-N920C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Galaxy Gear Live\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4; Gear Live Build/KMV78X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/19.77.34.5 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Samsung\",\n            \"model\": \"Gear Live\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/sharp.json",
    "content": "[\n    {\n        \"desc\": \"Sharp AQUOS-TVX19B\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; AQUOS-TVX19B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sharp\",\n            \"model\": \"AQUOS-TVX19B\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Sharp Aquos B10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; SH-A01) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sharp\",\n            \"model\": \"SH-A01\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sharp Aquos L2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; SH-L02 Build/S4045) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sharp\",\n            \"model\": \"SH-L02\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sharp Aquos L2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; SH-L02) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sharp\",\n            \"model\": \"SH-L02\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sharp Aquos R2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0; SHV42) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.92 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sharp\",\n            \"model\": \"SHV42\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Docomo SH-02M\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SH-02M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sharp\",\n            \"model\": \"SH-02M\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/smartfren.json",
    "content": "[\n    {\n        \"desc\": \"Smartfren Andromax L\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Andromax B26D2H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Smartfren\",\n            \"model\": \"Andromax B26D2H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Smartfren Andromax G2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Smartfren Andromax AD9A1H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.83 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Smartfren\",\n            \"model\": \"Andromax AD9A1H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Smartfren New Andromax I\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.1.2; id-id; New Andromax-i Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Smartfren\",\n            \"model\": \"New Andromax-i\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/sony.json",
    "content": "[\n    {\n        \"desc\": \"SONY Xperia 1 III\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; A101SO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"A101SO\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony G8141 (Xperia XZ1)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; SO-01K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"SO-01K\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony G8141 (Xperia XZ Premium)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; G8141) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"G8141\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony C5303 (Xperia SP)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.3; C5303 Build/12.1.A.1.205) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.93 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"C5303\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony SO-02F (Xperia Z1 F)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; SO-02F Build/14.1.H.2.119) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"SO-02F\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony D6653 (Xperia Z3)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4; D6653 Build/23.0.A.0.376) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"D6653\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia SOL25 (ZL2)\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4; SOL25 Build/17.1.1.C.1.64) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"SOL25\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia SP\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.3; C5302 Build/12.1.A.1.201) AppleWebkit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"C5302\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia L4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; XQ-AD51) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-AD51\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia 1ii\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; XQ-AT51) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-AT51\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia 1ii\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; SOG01) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"SOG01\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia 1 VI\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; XQ-EC44) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-EC44\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia 10ii\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; XQ-AU52) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-AU52\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia 10 III Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; XQ-BT44 Build/62.1.A.1.227; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 Sleipnir/3.6.0\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-BT44\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia 10 VI\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; XQ-ES72 Build/70.0.A.2.233; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.71 Mobile Safari/537.36 Line/14.16.0/IAB\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-ES72\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; XQ-AQ52) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.185 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-AQ52\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Sony XQ-AQ52) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-AQ52\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia Pro I\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; XQ-BE72) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.148 YaBrowser/22.7.3.82.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"XQ-BE72\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Sony SGP521 (Xperia Z2 Tablet)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4; SGP521 Build/17.1.A.0.432) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"Xperia Tablet\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Sony Xperia Z2 Tablet\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; SGP561) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"Xperia Tablet\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Sony Tablet S\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 3.1; Sony Tablet S Build/THMAS10000) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"Xperia Tablet\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Sony Tablet Z LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.1; SonySGP321 Build/10.2.C.0.143) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"Xperia Tablet\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Sony BRAVIA 4K GB ATV3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Andr0id 9; BRAVIA 4K GB ATV3 Build/PTT1.190515.001.S38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 OPR/46.0.2207.0 OMI/4.13.0.180.DIA5.104 Model/Sony-BRAVIA-4K-GB-ATV3\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"BRAVIA 4K GB ATV3\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Sony BRAVIA 4K GB ATV3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; BRAVIA 4K GB ATV3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"BRAVIA 4K GB ATV3\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Sony Bravia 4k UR2\",\n        \"ua\": \"Mozilla/5.0 (Linux: Andr0id 9: BRAVIA 4K UR2 Build/PTT1.190515.001.S104) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 OPR/46.0.2207.0 OMI/4.13.5.431.DIA5HBBTV.250 Model/Sony-BRAVIA-4K-UR2\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"BRAVIA 4K UR2\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"PlayStation 4\",\n        \"ua\": \"Mozilla/5.0 (PlayStation 4 3.00) AppleWebKit/537.73 (KHTML, like Gecko)\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"PlayStation 4\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"PlayStation 5\",\n        \"ua\": \"Mozilla/5.0 (Playstation; Playstation 5/1.05) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"Playstation 5\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"PlayStation Vita\",\n        \"ua\": \"Mozilla/5.0 (PlayStation Vita 3.52) AppleWebKit/537.73 (KHTML, like Gecko) Silk/3.2\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"PlayStation Vita\",\n            \"type\": \"console\"\n        }\n    },\n    {\n        \"desc\": \"Sony SmartWatch 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.2; SmartWatch 3 Build/LWX49K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/19.77.34.5 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Sony\",\n            \"model\": \"SmartWatch 3\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/t-mobile.json",
    "content": "[\n    {\n        \"desc\": \"T-Mobile REVVL 7 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; TMRV075G Build/UKQ1.230924.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/138.0.7204.146 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/521.0.0.42.97;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"T-Mobile\",\n            \"model\": \"TMRV075G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"T-Mobile REVVL Tab 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; TMRV5GTB Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/138.0.7204.179 Safari/537.36 musical_ly_2024009030 AppName/musical_ly ByteLocale/en\",\n        \"expect\": {\n            \"vendor\": \"T-Mobile\",\n            \"model\": \"TMRV5GTB\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"T-Mobile REVVL V+ 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; REVVL V+ 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 YaBrowser/21.11.1.114.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"T-Mobile\",\n            \"model\": \"REVVL V+ 5G\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/tcl.json",
    "content": "[\n    {\n        \"desc\": \"TCL 10 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T790Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 EdgA/114.0.1823.43\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T790Y\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 5G UW\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; T790S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T790S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T782H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36 OPR/64.3.3282.60839\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T782H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; T799B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T799B\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; T766H_RU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T766H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 TabMax\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 9296Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9296Q\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 TabMax 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; 9295G_EEA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9295G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10 TabMax WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; 9296G_TR) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9296G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10L\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; T770B Build/QKQ1.200329.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 GSA/11.41.10.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T770B\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 10L\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T770H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T770H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T781) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T781\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20 Pro 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T810S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Mobile Safari/537.36 EdgA/113.0.1774.63\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T810S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T671H Build/RKQ1.201112.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.73 Mobile Safari/537.36 GoogleApp/13.9.7.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T671H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20 XE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 5087Z) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"5087Z\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20B\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 6159K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6159K\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 205\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 4187D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"4187D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20E\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 6125A) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/18.0 Chrome/99.0.4844.88 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6125A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20L\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T774H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.59 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T774H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20L Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T775H Build/RKQ1.210107.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T775H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20R 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T767H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.97 Mobile Safari/537.36 OPR/71.3.3718.67322\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T767H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20S\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T773O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T773O\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 20Y\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 6156D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.134 Mobile Safari/537.36 OPR/70.3.3653.66287\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6156D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30 V 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; T781S Build/RKQ1.210614.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.166 Mobile Safari/537.36[FBAN/EMA;FBLC/en_US;FBAV/369.0.0.5.110;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T781S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30 XE 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T767W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/416.0.0.35.85;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T767W\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 305\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm; Android 11; 6102D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.167 YaBrowser/22.7.6.96.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6102D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 306\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; 6102H Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.141 Mobile Safari/537.36[FBAN/EMA;FBLC/it_IT;FBAV/332.0.0.22.108;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6102H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T676H Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T676H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30+\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T676J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T676J\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T776H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T776H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30 LE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; 4188V Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.136 Mobile Safari/537.36[FBAN/EMA;FBLC/en_US;FBAV/352.0.0.14.108;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"4188V\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; 6165H Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/396.1.0.28.104;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6165H\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 30E\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; 6127I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"6127I\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 40 NxtPaper\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; T612B Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.53 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T612B\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 4056S\",\n        \"ua\": \"Mozilla/5.0 (Mobile; TCL 4056S; rv:84.0) Gecko/84.0 Firefox/84.0 KAIOS/3.0\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"4056S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL A3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; A509DL Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 GSA/13.18.7.23.arm64\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"A509DL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL A30\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 5102L Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.136 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/413.0.0.30.104;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"5102L\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 40 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; T610K Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.166 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T610K\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 40 XE 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; T609DL Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.136 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/466.1.0.57.85;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T609DL\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 403\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T431D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T431D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 405\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T506D Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/418.0.0.33.69;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T506D\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 408\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; T507U Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.136 Mobile Safari/537.36 OPR/75.0.2254.68857\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T507U\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL 40R 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T771K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 EdgA/114.0.1823.37\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T771K\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL Ion X\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T430W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.60 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T430W\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL NxtPaper 11\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; 9466X Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.179 Safari/537.36 [FB_IAB/FB4A;FBAV/473.0.0.41.81;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9466X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Stylus 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; T779W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.2 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"T779W\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 8 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; 9048S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9048S\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 8 LE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; 9137W Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9137W\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 10 FHD 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 9060G Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9060G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 10 HD 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 9060X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9060X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 10 LTE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; 8196G Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.162 Safari/537.36 [FB_IAB/FB4A;FBAV/471.0.0.35.80;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"8196G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 10 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; 8496G Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.61 Safari/537.36 [FB_IAB/FB4A;FBAV/474.0.0.52.74;]\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"8496G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 10L\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 8491X_EEA Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.105 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"8491X\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Tab 10s 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 9080G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"9080G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"TCL Xess P17AA\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; TCL Xess P17AA Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TCL\",\n            \"model\": \"Xess P17AA\",\n            \"type\": \"tablet\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/technisat.json",
    "content": "[\n    {\n        \"desc\": \"TechniSAT Digit ISIO S SAT receiver\",\n        \"ua\": \"Opera/9.80 (Linux sh4; U; HbbTV/1.1.1 (;;;;;); CE-HTML; TechniSat Digit ISIO S; de) Presto/2.9.167 Version/11.50\",\n        \"expect\": {\n            \"vendor\": \"TechniSat\",\n            \"model\": \"Digit ISIO S\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"TechniSAT MultyVision SmartTV\",\n        \"ua\": \"Opera/9.80 (Linux i686; U; HbbTV/1.1.1 (;;;;;); CE-HTML; TechniSat MultyVision ISIO; de) Presto/2.9.167 Version/11.50\",\n        \"expect\": {\n            \"vendor\": \"TechniSat\",\n            \"model\": \"MultyVision ISIO\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/tecno.json",
    "content": "[\n    {\n        \"desc\": \"Tecno DroiPad 8D\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 5.1; TECNO DP8D Build/LMY47D; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36 OPR/42.0.2254.139280\",\n        \"expect\": {\n            \"vendor\": \"TECNO\",\n            \"model\": \"DP8D\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Tecno DroiPad 10A Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; TECNO DP10A Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TECNO\",\n            \"model\": \"DP10A Pro\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Tecno DroiPad 10D 4G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; TECNO P904) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36 OPR/77.0.4054.90\",\n        \"expect\": {\n            \"vendor\": \"TECNO\",\n            \"model\": \"P904\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Tecno KC8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; TECNO KC8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TECNO\",\n            \"model\": \"KC8\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Tecno Spark 8C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; TECNO KG5n) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"TECNO\",\n            \"model\": \"KG5n\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/tesla.json",
    "content": "[\n    {\n        \"desc\": \"Tesla\",\n        \"ua\": \"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/601.1 (KHTML, like Gecko) Tesla QtCarBrowser Safari/601.1\",\n        \"expect\": {\n            \"vendor\": \"Tesla\",\n            \"model\": \"undefined\",\n            \"type\": \"embedded\"\n        }\n    },\n    {\n        \"desc\": \"Tesla\",\n        \"ua\": \"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/2020.16.2.1-e99c70fff409\",\n        \"expect\": {\n            \"vendor\": \"Tesla\",\n            \"model\": \"undefined\",\n            \"type\": \"embedded\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/ulefone.json",
    "content": "[\n    {\n        \"desc\": \"Ulefone Armor\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Armor Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Armor\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 6.0; Armor) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 YaBrowser/20.4.2.101.00 SA/1 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Armor 8 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Armor 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.192 Mobile Safari/537.36 OPR/74.1.3922.71199\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor 8 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Armor 12 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Armor 12 5G Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.166 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor 12 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Armor 20WT\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Armor 20WT) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/22.0 Chrome/111.0.5563.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor 20WT\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Armor Pad\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Armor Pad Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/431.0.0.30.108;]\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor Pad\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Armor X5 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Armor X5 Pro Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/430.0.0.23.113;]\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Armor X5 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Power Armor 14 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Power Armor14 Pro Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Power Armor14 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Power Armor 18T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Power Armor 18T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Power Armor 18T\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Ulefone Power Armor 19T\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; Power Armor 19T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.192 Mobile Safari/537.36 OPR/74.3.3922.71982\",\n        \"expect\": {\n            \"vendor\": \"Ulefone\",\n            \"model\": \"Power Armor 19T\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/valve.json",
    "content": "[\n    {\n        \"desc\": \"Valve\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Valve Steam Client/Steam Deck [Steam Deck Beta]/default/0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Valve\",\n            \"model\": \"Steam Deck\",\n            \"type\": \"console\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/vivo.json",
    "content": "[\n    {\n        \"desc\": \"Vivo S1 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; vivo 1920) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"1920\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo Y52s\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; V2057A Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.10 SP-engine/2.28.0 baiduboxapp/12.10.0.10 (Baidu; P1 10) NABar/1.0\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"V2057A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo X60\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; V2046A; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/8.8.71.0\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"V2046A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo Y79A\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.2; vivo Y79A Build/N2G47H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/9.0.14.0\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"Y79A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo Y93\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; vivo 1814) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"1814\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo Y97\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1.0; V1813T Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/9.0.14.0\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"V1813T\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo iQOO Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; V1916A; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/9.1.10.6\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"V1916A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Vivo 1906 (Y11)\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; vivo 1906) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Vivo\",\n            \"model\": \"1906\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/vizio.json",
    "content": "[\n    {\n        \"desc\": \"VIZIO\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 CrKey/1.0.999999 VIZIO SmartCast(Conjure/SX7B-4.6.419.12 FW/7.0.23.2-4 Model/M557-G0)\",\n        \"expect\": {\n            \"vendor\": \"VIZIO\",\n            \"model\": \"M557-G0\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"VIZIO\",\n        \"ua\": \"VIZIO V506-J09 ViziOS/1.4.512.847.1 WatchFree/24.06.13.2 FancyPlayer/1.1.30-qa \",\n        \"expect\": {\n            \"vendor\": \"VIZIO\",\n            \"model\": \"V506-J09\",\n            \"type\": \"smarttv\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/wiko.json",
    "content": "[\n    {\n        \"desc\": \"Wiko Life 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Wiko U316AT) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5199.205 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Wiko\",\n            \"model\": \"U316AT\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Wiko Ride 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; Wiko U614AS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Wiko\",\n            \"model\": \"U614AS\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Wiko T10\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; WIKO T10 Build/RP1A.200720.011) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.62 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"WIKO\",\n            \"model\": \"T10\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/xiaomi.json",
    "content": "[\n    {\n        \"desc\": \"MIUI Xiaomi Mi MIX 3 5G\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 9; Mi MIX 3 5G MIUI/V10.3.2.0.PEMEUVF)\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi MIX 3 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"MIUI POCOPHONE F1\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 9; POCOPHONE F1 MIUI/9.6.27)\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"POCOPHONE F1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"MIUI Xiaomi M2006C3MT\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 10; M2006C3MT MIUI/V12.0.7.0.QCRMIXM)\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2006C3MT\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi 2201117TG\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; 2201117TG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"2201117TG\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi M2004J19C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; M2004J19C Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.77 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2004J19C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi M2006C3MNG\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; M2006C3MNG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2006C3MNG\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi 21061119DG\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; 21061119DG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 YaBrowser/23.3.7.24.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"21061119DG\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi 2013023\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; en-US; 2013023 Build/HM2013023) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/10.0.1.512 U3/0.8.0 Mobile Safari/533.1\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"2013023\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Black Shark 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; zh-CN; SHARK KLE-A0 Build/KLEN2211210CN00MR6) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/17.3.8.1369 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"SHARK KLE-A0\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Black Shark 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; en-US; SHARK PRS-H0 Build/PROS2203060OS00MP5) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.4.0.1306 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"SHARK PRS-H0\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Black Shark 4 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; es-us; SHARK KSR-H0 Build/KASE2208050OS00MP4) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.22.1-gn\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"SHARK KSR-H0\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Black Shark 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 12; SHARK PAR-H0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 YaBrowser/23.5.0.256.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"SHARK PAR-H0\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Civi 5 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 15; zh-CN; 25067PYE3C Build/AQ3A.250129.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 UCBrowser/18.0.4.1430 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"25067PYE3C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Hongmi Note 1W\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.2; zh-CN; HM NOTE 1W Build/JDQ39) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.7.9.439 U3/0.8.0 Mobile Safari/533.1\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"HM NOTE 1W\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 3C\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.3; zh-CN; MI 3C Build/JLS36C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.7.9.439 U3/0.8.0 Mobile Safari/533.1\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI 3C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.0; MI 5 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.83 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI 5\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1; MI 6 Build/NMF26X; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/59.0.3071.125 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI 6\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 10 Pro\",\n        \"ua\": \"Linux; U; Android 13; Mi 10 Pro Build/TKQ1.221114.001\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi 10 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 11 Lite 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; zh-CN; Mi 11 Lite 5G Build/SKQ1.211006.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.136 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.17.0-gn\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi 11 Lite 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 5s Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; zh-cn; MI 5s Plus Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/8.7.1\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI 5s Plus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi A1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.0.0; Mi A1 Build/OPR1.170623.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi A1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Note\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.4; MI NOTE LTE Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI NOTE LTE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi One Plus\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; MI-ONE Plus Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI-ONE Plus\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Max 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; MI MAX 3 Build/PKQ1.181007.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI MAX 3\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi A1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Mi A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.101 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi A1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi A2 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Mi A2 Lite) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.62 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi A2 Lite\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 9 SE\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Mi 9 SE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi 9 SE\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi 10T\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; fr-CA; Mi 10T Build/SKQ1.211006.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.79 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.16.1-gn\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi 10T\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi A2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Mi A2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi A2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi CC9\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 11; zh-cn; MI CC 9 Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.116 Mobile Safari/537.36 XiaoMi/MiuiBrowser/15.5.18\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI CC 9\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.4; en-us; MI PAD Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.3.2\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI PAD\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; MI PAD 2 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Safari/537.36 [FB_IAB/FB4A;FBAV/137.0.0.24.91;]\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI PAD 2\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; x86_64; Android 5.1; MI PAD 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 YaBrowser/20.11.2.69.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI PAD 2\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 7.0; MI PAD 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.216 YaBrowser/21.5.6.56.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI PAD 3\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD 4\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 8.1.0; MI PAD 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 YaBrowser/19.9.1.126.01 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI PAD 4\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD 4 PLUS\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; MI PAD 4 PLUS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MI PAD 4 PLUS\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi MI PAD 4 WiFi\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 8.1; Mi Pad4 Wi-Fi) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Mobile Safari/537.36 EdgA/86.0.622.61\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi Pad4 Wi-Fi\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Pad 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; 21051182G Build/TKQ1.221013.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36 Flipboard/4.3.31/5486,4.3.31.5486\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"21051182G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Pad 5 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; M2105K81AC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Safari/537.36 Line/13.15.1/IAB\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2105K81AC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Pad 5 Pro 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; M2105K81C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2105K81C\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Pad 6 Max 14\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 14; zh-tw; 2307BRPDCC Build/UKQ1.230804.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.118 Mobile Safari/537.36 Device/yudi Model/2307BRPDCC XiaoMi/MiuiBrowser/14.10.6\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"2307BRPDCC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Pad 6 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 13; en-US; 23046RP50C Build/TKQ1.221114.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.6.2.1316 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"23046RP50C\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Pad 5\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; ca-ES; Xiaomi Pad 5 Build/SKQ1.220303.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.86 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.6.0-gn\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"mi Pad 5\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Pad 6S Pro 12.4\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; 24018RPACC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"24018RPACC\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO X2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; POCO X2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"POCO X2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO X3 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 11; M2102J20SI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2102J20SI\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO X3 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2102J20SG\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO X3 NFC\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; M2007J20CG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2007J20CG\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO M2 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; arm_64; Android 11; POCO M2 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 YaBrowser/22.11.7.42.00 SA/3 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"POCO M2 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCO M3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; M2010J19CI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2010J19CI\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi POCOPHONE F1\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; POCOPHONE F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"POCOPHONE F1\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Qin 1s+\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.4.4; Qin 1s+ Build/KTU84P; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36 OPR/46.0.2254.145391\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Qin 1s+\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Qin 2\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; Qin 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Qin 2\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Qin 2 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9.0; QIN2 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4215.0 Mobile Safari/537.36 EdgA/86.0.597.0\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"QIN2 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Qin 3 Ultra\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; QIN3ULTRA Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/128.0.6613.120 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"QIN3ULTRA\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi 4A\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; Redmi 4A Build/MMB29M; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi 4A\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi 10C\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; 220333QAG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"220333QAG\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi 15\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 15; 25062RN2DA Build/AQ3A.250226.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/142.0.7444.212 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/541.0.0.49.79;IABMV/1;]\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"25062RN2DA\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi K30 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Redmi K30 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi K30 5G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi K30 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Redmi K30 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi K30 Pro\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi Note 3\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; Redmi Note 3 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.116 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi Note 3\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Redmi Note 9 Pro Max\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Redmi Note 9 Pro Max) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi Note 9 Pro Max\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 9S\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Redmi Note 9S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi Note 9S\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 10 5G\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; M2103K19C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2103K19C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 10 Lite\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; es-VE; Mi Note 10 Lite Build/SKQ1.210908.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.88 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.16.1-gn\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Mi Note 10 Lite\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 10 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; M2101K6P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2101K6P\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 10 Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 12; M2101K6G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"M2101K6G\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 8\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; Redmi Note 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi Note 8\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Note 12 Turbo\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 13; 23049RAD8C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36 VivoBrowser/16.7.1.1\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"23049RAD8C\",\n            \"type\": \"mobile\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Pad\",\n        \"ua\": \"Mozilla/5.0 (Linux; U; Android 12; id-id; Redmi Pad Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.136 Mobile Safari/537.36 XiaoMi/MiuiBrowser/14.1.1-gn\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Redmi Pad\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Pad\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; 22081283G Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Safari/537.36 Flipboard/4.3.31/5486,4.3.31.5486\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"22081283G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Pad Pro\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; 2405CRPFDG Build/UKQ1.240116.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.97 Safari/537.36 [FB_IAB/FB4A;FBAV/476.0.0.49.74;] FBNV/1\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"2405CRPFDG\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Pad SE\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 14; 23073RPBFG Build/UKQ1.231003.002)\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"23073RPBFG\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"XiaoMi Redmi Pad SE 8.7\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 14; 24076RP19G Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.107 Mobile Safari/537.36 Line/14.18.1/IAB\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"24076RP19G\",\n            \"type\": \"tablet\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 10; MiTV-MOOQ0 Build/QTG3.200305.006; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/94.0.4606.61 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MiTV-MOOQ0\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi TV\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; MiTV4I Build/PI; en-in) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36 Puffin/7.8.3.40913AP\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MiTV4I\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Mi Box\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 9; MIBOX3 Build/PI; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/119.0.6045.193 Mobile Safari/537.36\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"MIBOX3\",\n            \"type\": \"smarttv\"\n        }\n    },\n    {\n        \"desc\": \"Xiaomi Watch 2 Pro\",\n        \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 13; Xiaomi Watch 2 Pro Build/TWR7.231031.001.XM064S)\",\n        \"expect\": {\n            \"vendor\": \"Xiaomi\",\n            \"model\": \"Watch 2 Pro\",\n            \"type\": \"wearable\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/device/zte.json",
    "content": "[\n    {\n        \"desc\": \"ZTE Blade A6\",\n        \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; ZTE BLADE A0620 Build/NMF26F; ru-ru) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36 Puffin/9.2.0.50586AP\",\n        \"expect\": {\n            \"vendor\": \"ZTE\",\n            \"model\": \"BLADE A0620\",\n            \"type\": \"mobile\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/engine/engine-all.json",
    "content": "[\n    {\n        \"desc\"    : \"ArkWeb\",\n        \"ua\"      : \"Mozilla/5.0 (Phone; OpenHarmony 4.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ArkWeb\",\n            \"version\" : \"4.1.6.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Blink\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; SM-G920I Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/3.4.9 SamsungBrowser/4.0 Chrome/57.0.2987.146 Mobile VR Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Blink\",\n            \"version\" : \"57.0.2987.146\"\n        }\n    },\n    {\n        \"desc\"    : \"Dillo\",\n        \"ua\"      : \"Dillo/3.1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dillo\",\n            \"version\" : \"3.1.0\"\n        }\n    },\n    {\n        \"desc\"    : \"EdgeHTML\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"EdgeHTML\",\n            \"version\" : \"12.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Flow\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) EkiohFlow/5.7.4.30559 Flow/5.7.4 (like Gecko Firefox/53.0 rv:53.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Flow\",\n            \"version\" : \"5.7.4.30559\"\n        }\n    },\n    {\n        \"desc\"    : \"Gecko\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; rv:2.0b9pre) Gecko/20110111 Firefox/4.0b9pre\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Gecko\",\n            \"version\" : \"2.0b9pre\"\n        }\n    },\n    {\n        \"desc\"    : \"Goanna\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 5.1; rv:38.9) Gecko/20100101 Goanna/2.2 Firefox/38.9 PaleMoon/26.5.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Goanna\",\n            \"version\" : \"2.2\"\n        }\n    },\n    {\n        \"desc\"    : \"KHTML\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"KHTML\",\n            \"version\" : \"4.5.4\"\n        }\n    },\n    {\n        \"desc\"    : \"LibWeb\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; x86_64) Ladybird/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LibWeb\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"LibWeb\",\n        \"ua\"      : \"Mozilla/4.0 (SerenityOS; x86) LibWeb+LibJS (Not KHTML, nor Gecko) LibWeb\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LibWeb\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"NetFront\",\n        \"ua\"      : \"Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NetFront\",\n            \"version\" : \"3.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Presto\",\n        \"ua\"      : \"Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Presto\",\n            \"version\" : \"2.8.149\"\n        }\n    },\n    {\n        \"desc\"    : \"Servo\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Servo/1.0 Firefox/111.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Servo\",\n            \"version\" : \"1.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Tasman\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; PPC Mac OS X 10.4.7; Tasman 1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tasman\",\n            \"version\" : \"1.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Trident\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Trident\",\n            \"version\" : \"6.0\"\n        }\n    },\n    {\n        \"desc\"    : \"WebKit\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WebKit\",\n            \"version\" : \"533.19.4\"\n        }\n    },\n    {\n        \"desc\"    : \"WebKit\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/27.0.1453.110 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WebKit\",\n            \"version\" : \"537.36\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 5.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 WebAppManager\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Blink\",\n            \"version\" : \"68.0.3440.106\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 4.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.34 Safari/537.36 WebAppManager\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Blink\",\n            \"version\" : \"53.0.2785.34\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 3.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.2.1 Chrome/38.0.2125.122 Safari/537.36 WebAppManager\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Blink\",\n            \"version\" : \"38.0.2125.122\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 2.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/538.2 (KHTML, like Gecko) Large Screen WebAppManager Safari/538.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WebKit\",\n            \"version\" : \"538.2\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 1.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WebKit\",\n            \"version\" : \"537.41\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/extension/cli.json",
    "content": "[\n    {\n        \"desc\"    : \"curl\",\n        \"ua\"      : \"curl/7.38.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"curl\",\n            \"version\" : \"7.38.0\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"ELinks\",\n        \"ua\"      : \"ELinks/0.11.4-3-lite (textmode; Debian; Linux 2.6.26-1-686 i686;\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ELinks\",\n            \"version\" : \"0.11.4-3-lite\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"ELinks\",\n        \"ua\"      : \"ELinks (0.11.3; Linux 2.6.23-hardened-r4 i686; 166x55)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ELinks\",\n            \"version\" : \"0.11.3\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"HTTPie\",\n        \"ua\"      : \"HTTPie/0.9.9\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HTTPie\",\n            \"version\" : \"0.9.9\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"lynx\",\n        \"ua\"      : \"Lynx 2.8.8dev.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Lynx\",\n            \"version\" : \"2.8.8dev.3\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"lynx\",\n        \"ua\"      : \"Lynx/2.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Lynx\",\n            \"version\" : \"2.6\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"PowerShell\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PowerShell\",\n            \"version\" : \"6.0.0\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"PowerShell\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT; Windows NT 10.0; de-DE) WindowsPowerShell/5.1.19041.5737\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PowerShell\",\n            \"version\" : \"5.1.19041.5737\",\n            \"type\"    : \"cli\"\n        }\n    },\n    {\n        \"desc\"    : \"wget\",\n        \"ua\"      : \"Wget/1.21.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Wget\",\n            \"version\" : \"1.21.1\",\n            \"type\"    : \"cli\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/extension/crawler.json",
    "content": "[\n    {\n        \"desc\"    : \"360Spider\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider\",\n        \"expect\"  :\n        {\n            \"name\"    : \"360Spider\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AdIdxBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; adidxbot/2.0; +http://www.bing.com/bingbot.htm)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"adidxbot\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AdsBot Mobile Web\",\n        \"ua\"      : \"AdsBot-Google (+http://www.google.com/adsbot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AdsBot-Google\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AdsBot Mobile Web\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; AdsBot-Google-Mobile; +http://www.google.com/mobile/adsbot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AdsBot-Google-Mobile\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AdSense\",\n        \"ua\"      : \"Mediapartners-Google\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mediapartners-Google\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AhrefsBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AhrefsBot\",\n            \"version\" : \"7.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AI2Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible) AI2Bot (+https://www.allenai.org/crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AI2Bot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"aiHitBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; aiHitBot/2.9; +https://www.aihitdata.com/about)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"aiHitBot\",\n            \"version\" : \"2.9\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Algolia Crawler\",\n        \"ua\"      : \"Algolia Crawler/v2.183.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Algolia Crawler\",\n            \"version\" : \"v2.183.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Algolia Crawler Renderscript\",\n        \"ua\"      : \"Algolia Crawler Renderscript\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Algolia Crawler Renderscript\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Applebot\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B410 Safari/600.1.4 (Applebot/0.1;+http://www.apple.com/go/applebot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Applebot\",\n            \"version\" : \"0.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Applebot-Extended\",\n        \"ua\"      : \"Applebot-Extended\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Applebot-Extended\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Amazonbot\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Amazonbot\",\n            \"version\" : \"0.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Anthropic AI\",\n        \"ua\"      : \"anthropic-ai\",\n        \"expect\"  :\n        {\n            \"name\"    : \"anthropic-ai\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Archive.org Bot\",\n        \"ua\"      : \"ia_archiver/8.1 (Windows 2000 1.9; en-US;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ia_archiver\",\n            \"version\" : \"8.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Archive.org Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; archive.org_bot/3.3.0 +https://archive.org/details/archive.org_bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"archive.org_bot\",\n            \"version\" : \"3.3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"atlassian-bot\",\n        \"ua\"      : \"atlassian-bot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"atlassian-bot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Audisto Crawler\",\n        \"ua\"      : \"Audisto Crawler (mobile; +https://audisto.com/bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Audisto Crawler\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Audisto Crawler\",\n        \"ua\"      : \"Audisto Crawler (desktop; +https://audisto.com/bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Audisto Crawler\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Audisto Crawler\",\n        \"ua\"      : \"Audisto Crawler (mobile; essential; +https://audisto.com/bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Audisto Crawler\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Audisto Crawler\",\n        \"ua\"      : \"Audisto Crawler (desktop; essential; +https://audisto.com/bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Audisto Crawler\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AwarioBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; AwarioBot/1.0; +https://awario.com/bots.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AwarioBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AwarioSmartBot\",\n        \"ua\"      : \"AwarioSmartBot/1.0 (+https://awario.com/bots.html; bots@awario.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AwarioSmartBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"AwarioRssBot\",\n        \"ua\"      : \"AwarioRssBot/1.0 (+https://awario.com/bots.html; bots@awario.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AwarioRssBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baidu ADS\",\n        \"ua\"      : \"Baidu-ADS\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baidu-ADS\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-ads\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0; Baiduspider-ads) Gecko/17.0 Firefox/17.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-ads\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-cpro\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Baiduspider-cpro; +http://www.baidu.com/search/spider.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-cpro\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-favo\",\n        \"ua\"      : \"Baiduspider-favo\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-favo\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-image\",\n        \"ua\"      : \"Baiduspider-image+(+http://www.baidu.com/search/spider.htm)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-image\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-news\",\n        \"ua\"      : \"Baiduspider-news\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-news\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-render\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-render\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Baiduspider-video\",\n        \"ua\"      : \"Baiduspider-video\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Baiduspider-video\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Bingbot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) Chrome/\",\n        \"expect\"  :\n        {\n            \"name\"    : \"bingbot\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"BLEXBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; BLEXBot/1.0; +http://webmeup-crawler.com/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BLEXBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"botify\",\n        \"ua\"      : \"Desktop: Mozilla/5.0 (compatible; botify; http://botify.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"botify\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Bravebot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Bravebot/1.0; +https://search.brave.com/help/brave-search-crawler) Chrome/W.X.Y.Z Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bravebot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"BrightEdge Crawler\",\n        \"ua\"      : \"BrightEdge Crawler/1.0 (crawler@brightedge.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BrightEdge Crawler\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Bytespider\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.1511.1269 Mobile Safari/537.36; Bytespider\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bytespider\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"ClaudeBot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ClaudeBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"CCBot\",\n        \"ua\"      : \"CCBot/1.0 (+https://commoncrawl.org/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"CCBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"ChatGLM-Spider\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; ChatGLM-Spider/1.0; +https://chatglm.cn/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ChatGLM-Spider\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Claude-SearchBot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Claude-SearchBot/1.0; +Claude-SearchBot@anthropic.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Claude-SearchBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"ClaudeWeb\",\n        \"ua\"      : \"Claude-Web/1.0 (web crawler; +https://www.anthropic.com/; bots@anthropic.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Claude-Web\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Cloudflare AutoRAG\",\n        \"ua\"      : \"Cloudflare-AutoRAG (https://developers.cloudflare.com/autorag; autorag@cloudflare.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Cloudflare-AutoRAG\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Coc Coc Bot (web)\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; coccocbot-web/1.0; +http://help.coccoc.com/searchengine)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"coccocbot-web\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Coc Coc Bot (image)\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; coccocbot-image/1.0; +http://help.coccoc.com/searchengine)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"coccocbot-image\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"cohere-training-data-crawler\",\n        \"ua\"      : \"cohere-training-data-crawler (+crawler@cohere.ai)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"cohere-training-data-crawler\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"contxbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible;contxbot/1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"contxbot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Cotoyogi\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Cotoyogi/4.0; +https://ds.rois.ac.jp/center8/crawler/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Cotoyogi\",\n            \"version\" : \"4.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Coveobot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) (compatible; Coveobot/2.0;+http://www.coveo.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Coveobot\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"CriteoBot\",\n        \"ua\"      : \"CriteoBot/0.1 (+https://www.criteo.com/criteo-crawler/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"CriteoBot\",\n            \"version\" : \"0.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"DataForSEO\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; DataForSeoBot; +https://dataforseo.com/dataforseo-bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DataForSeoBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Daum\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE or Firefox mutant;) Daum 4.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Daum\",\n            \"version\" : \"4.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Daumoa\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server;) Daumoa 4.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Daumoa\",\n            \"version\" : \"4.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Daumoa-image\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server;) Daumoa-image/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Daumoa-image\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"DeepSeekBot\",\n        \"ua\"      : \"DeepSeekBot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DeepSeekBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Diffbot\",\n        \"ua\"      : \"Diffbot/0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Diffbot\",\n            \"version\" : \"0.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Dotbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; DotBot/1.2; +https://opensiteexplorer.org/dotbot; help@moz.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DotBot\",\n            \"version\" : \"1.2\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"DuckDuckBot\",\n        \"ua\"      : \"DuckDuckBot/1.1; ( http://duckduckgo.com/duckduckbot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DuckDuckBot\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"DuckDuckGo-Favicons-Bot\",\n        \"ua\"      : \"DuckDuckGo-Favicons-Bot/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DuckDuckGo-Favicons-Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Elastic\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/124.0.6367.29 Safari/537.36 Elastic/Synthetics\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Elastic\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Exabot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Exabot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"FacebookBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/\",\n        \"expect\"  :\n        {\n            \"name\"    : \"FacebookBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"FacebookExternalHit\",\n        \"ua\"      : \"facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"facebookexternalhit\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"FacebookExternalHit\",\n        \"ua\"      : \"facebookcatalog/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"facebookcatalog\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"FirecrawlAgent\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; FirecrawlAgent/1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"FirecrawlAgent\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Freespoke\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Freespoke/2.0; +https://docs.freespoke.com/search/bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Freespoke\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"APIs-Google\",\n        \"ua\"      : \"APIs-Google (+https://developers.google.com/webmasters/APIs-Google.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"APIs-Google\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Googlebot-Video\",\n        \"ua\"      : \"Googlebot-Video/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Googlebot-Video\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Googlebot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Googlebot\",\n            \"version\" : \"2.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Googlebot Image\",\n        \"ua\"      : \"Googlebot-Image/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Googlebot-Image\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Googlebot Video\",\n        \"ua\"      : \"Googlebot-Video/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Googlebot-Video\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Googlebot News\",\n        \"ua\"      : \"Googlebot-News/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Googlebot-News\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Storebot\",\n        \"ua\"      : \"Storebot-Google/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Storebot-Google\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Google InspectionTool\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Google-InspectionTool/1.0;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-InspectionTool\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"GoogleOther\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GoogleOther) Chrome/41.0.2272.96 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoogleOther\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"GoogleOther-Image\",\n        \"ua\"      : \"GoogleOther-Image/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoogleOther-Image\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"GoogleOther-Video\",\n        \"ua\"      : \"GoogleOther-Video/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoogleOther-Video\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Google-CloudVertexBot\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.7204.183 Mobile Safari/537.36 (compatible; Google-CloudVertexBot; +https://cloud.google.com/enterprise-search)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-CloudVertexBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Google-NotebookLM\",\n        \"ua\"      : \"Google-NotebookLM\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-NotebookLM\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Google-Safety\",\n        \"ua\"      : \"Google-Safety\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-Safety\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"GPTBot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GPTBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Headline\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; ev-crawler/1.0; +https://headline.com/legal/crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Headline\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"HubSpot Crawler\",\n        \"ua\"      : \"HubSpot Crawler 1.0 http://www.hubspot.com/\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HubSpot Crawler\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"HuggingFace-Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; HuggingFace-Bot/1.0; +https://huggingface.co/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HuggingFace-Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"iAskBot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/605.1.15 (KHTML, like Gecko; compatible; iAskBot/1.0; +https://iask.ai/) Chrome/120.0.6099.119 Safari/605.1.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iAskBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"ImagesiftBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; ImagesiftBot; +imagesift.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ImagesiftBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Kagibot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Kagibot/1.0; +https://kagi.com/bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Kagibot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Kangaroo Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Kangaroo Bot/1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Kangaroo Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Linespider\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Linespider/1.1; +https://lin.ee/4dwXkTH)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Linespider\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"LinkedInBot\",\n        \"ua\"      : \"LinkedInBot/1.0 (compatible; Mozilla/5.0; Apache-HttpClient +http://www.linkedin.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"LinkedInBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"magpie-crawler\",\n        \"ua\"      : \"magpie-crawler/1.1 (robots-txt-checker; +http://www.brandwatch.net)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"magpie-crawler\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Marginalia Search\",\n        \"ua\"      : \"search.marginalia.nu\",\n        \"expect\"  :\n        {\n            \"name\"    : \"marginalia\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Meta-ExternalAgent\",\n        \"ua\"      : \"meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"meta-externalagent\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Meta-ExternalAds\",\n        \"ua\"      : \"meta-externalads/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"meta-externalads\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Meta-WebIndexer\",\n        \"ua\"      : \"meta-webindexer/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"meta-webindexer\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"MJ12bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MJ12bot/v1.4.8; http://mj12bot.com/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MJ12bot\",\n            \"version\" : \"v1.4.8\",\n            \"major\"   : \"1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"MojeekBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MojeekBot/0.11; +https://www.mojeek.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MojeekBot\",\n            \"version\" : \"0.11\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"msnbot\",\n        \"ua\"      : \"msnbot/2.0b (+http://search.msn.com/msnbot.htm)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"msnbot\",\n            \"version\" : \"2.0b\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Omgili\",\n        \"ua\"      : \"omgili/0.5 +https://omgili.com\",\n        \"expect\"  :\n        {\n            \"name\"    : \"omgili\",\n            \"version\" : \"0.5\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Omgilibot\",\n        \"ua\"      : \"omgilibot/0.3 +http://www.omgili.com/Crawler.html\",\n        \"expect\"  :\n        {\n            \"name\"    : \"omgilibot\",\n            \"version\" : \"0.3\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"OnCrawl\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 (compatible; OnCrawl Mobile/1.0; +http://www.oncrawl.com/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OnCrawl\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Onespot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Onespot-ScraperBot/1.0; +https://www.onespot.com/identifying-traffic.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Onespot-ScraperBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"OpenAI Search\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OAI-SearchBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"PanguBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; PanguBot/1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PanguBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"PerplexityBot\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PerplexityBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"PetalBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible;PetalBot; +https://webmaster.petalsearch.com/site/petalbot) \",\n        \"expect\"  :\n        {\n            \"name\"    : \"PetalBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"PetalBot\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0;) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; PetalBot;+https://webmaster.petalsearch.com/site/petalbot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PetalBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Proximic\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; proximic; +https://www.comscore.com/Web-Crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"proximic\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Qwantbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Qwantbot/1.0_12345; +https://help.qwant.com/bot/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Qwantbot\",\n            \"version\" : \"1.0_12345\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Qwantbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Qwantbot-prod51071/1.0; +Qwantbot@qwant.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Qwantbot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Qwantbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Qwantbot-news/2.0;  +https://help.qwant.com/bot/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Qwantbot-news\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Replicate-Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Replicate-Bot/1.0; +https://replicate.com/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Replicate-Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"RunPod-Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; RunPod-Bot/1.0; +https://runpod.io/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"RunPod-Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SBIntuitionsBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SBIntuitionsBot/0.1;+https://www.sbintuitions.co.jp/bot/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SBIntuitionsBot\",\n            \"version\" : \"0.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SeekportBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SeekportBot; +https://bot.seekport.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SeekportBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SemrushBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SemrushBot\",\n            \"version\" : \"7\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SemrushBot for Backlink Audit tool\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SemrushBot-BA; +http://www.semrush.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SemrushBot-BA\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SemrushBot for On Page SEO Checker tool\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SemrushBot-SI/0.97; +http://www.semrush.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SemrushBot-SI\",\n            \"version\" : \"0.97\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SemrushBot for ContentShake AI tool\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SemrushBot-OCOB/1; +https://www.semrush.com/bot/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SemrushBot-OCOB\",\n            \"version\" : \"1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SemrushBot for SEO Writing Assistant tool\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SemrushBot-SWA/0.1; +http://www.semrush.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SemrushBot-SWA\",\n            \"version\" : \"0.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SeznamBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SeznamBot/4.0-RC1; +http://napoveda.seznam.cz/seznambot-intro/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SeznamBot\",\n            \"version\" : \"4.0-RC1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Siteimprove\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; SiteCheck-sitecrawl by Siteimprove.com; +https://siteimprove.com/bots) Chrome/[VERSION] Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Siteimprove\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Sogou Pic Spider\",\n        \"ua\"      : \"Sogou Pic Spider/3.0( http://www.sogou.com/docs/help/webmasters.htm#07)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sogou Pic Spider\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Sogou web spider\",\n        \"ua\"      : \"Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sogou web spider\",\n            \"version\" : \"4.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Startpage\",\n        \"ua\"      : \"StartpagePrivateImageProxy/3.0 (https://www.startpage.com/; support@startpage.com) aiohttp.client/3.11.11\",\n        \"expect\"  :\n        {\n            \"name\"    : \"StartpagePrivateImageProxy\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"SurdotlyBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SurdotlyBot/1.0; +http://sur.ly/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SurdotlyBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Swiftbot\",\n        \"ua\"      : \"Swiftbot/1.0 (swiftype.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Swiftbot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Teoma\",\n        \"ua\"      : \"Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Teoma\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"TikTokSpider\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; TikTokSpider; ttspider-feedback@tiktok.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"TikTokSpider\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Timpibot\",\n        \"ua\"      : \"Timpibot/0.8 (+http://www.timpi.io)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Timpibot\",\n            \"version\" : \"0.8\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Together-Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Together-Bot/1.0; +https://together.ai/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Together-Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"TurnitinBot\",\n        \"ua\"      : \"TurnitinBot (https://turnitin.com/robot/crawlerinfo.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"TurnitinBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"TwinAgent\",\n        \"ua\"      : \"TwinAgent/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"TwinAgent\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"xAI-Bot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; xAI-Bot/1.0; +https://x.ai/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"xAI-Bot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"VelenPublicWebCrawler\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; VelenPublicWebCrawler/1.0; +https://velen.io)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"VelenPublicWebCrawler\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"v0bot\",\n        \"ua\"      : \"v0bot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"v0bot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"webzio\",\n        \"ua\"      : \"webzio (+https://webz.io/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webzio\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Webzio-Extended\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Webzio-Extended/1.0; +https://www.webzio.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Webzio-Extended\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YaCy\",\n        \"ua\"      : \"yacybot (/global; amd64 FreeBSD 14.3-STABLE; java 19.0.2; Europe/en) https://yacy.net/bot.html\",\n        \"expect\"  :\n        {\n            \"name\"    : \"yacybot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Yahoo! Japan\",\n        \"ua\"      : \"Y!J-BRW/1.0 (https://www.yahoo-help.jp/app/answers/detail/p/595/a_id/42716)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Y!J-BRW\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Yahoo! Slurp\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)  \",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yahoo! Slurp\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexAccessibilityBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexAccessibilityBot/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexAccessibilityBot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexAdditionalBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexAdditionalBot/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexAdditionalBot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexAdNet\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexAdNet/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexAdNet\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexBlogs\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexBlogs/0.99; robot; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexBlogs\",\n            \"version\" : \"0.99\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexBot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexBot MirrorDetector\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexBot/3.0; MirrorDetector; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexBot MirrorDetector\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexComBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexComBot/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexComBot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexFavicons\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexFavicons/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexFavicons\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexImageResizer\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexImageResizer/2.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexImageResizer\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexImages\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexImages/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexImages\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexMarket\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexMarket/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexMarket\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexMetrika\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexMetrika/2.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexMetrika\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexMedia\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexMedia/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexMedia\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexMobileBot\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4 (compatible; YandexMobileBot/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexMobileBot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexMobileScreenShotBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexMobileScreenShotBot/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexMobileScreenShotBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexNews\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexNews/4.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexNews\",\n            \"version\" : \"4.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexOntoDB\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexOntoDB/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexOntoDB\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexOntoDBAPI\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexOntoDBAPI/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexOntoDBAPI\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexPartner\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexPartner/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexPartner\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexRCA\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexRCA/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexRCA\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexRenderResourcesBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexRenderResourcesBot/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexRenderResourcesBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexScreenshotBot\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Safari/537.36 (compatible; YandexScreenshotBot/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexScreenshotBot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexSpravBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexSpravBot/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexSpravBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexTracker\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexTracker/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexTracker\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexVertis\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexVertis/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexVertis\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexVerticals\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexVerticals/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexVerticals\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexVideo\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexVideo/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexVideo\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexVideoParser\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexVideoParser/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexVideoParser\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexWebmaster\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexWebmaster/2.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexWebmaster\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YepBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YepBot/1.0; +http://yep.com/yepbot/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YepBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"Yeti\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Yeti/1.1; +http://naver.me/spd)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yeti\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YisouSpider\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 YisouSpider/5.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YisouSpider\",\n            \"version\" : \"5.0\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YisouSpider\",\n        \"ua\"      : \"YisouSpider\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YisouSpider\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"YouBot\",\n        \"ua\"      : \"YouBot (+http://www.you.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YouBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"crawler\"\n        }\n    },\n    {\n        \"desc\"    : \"ZumBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; ZumBot/1.0; http://help.zum.com/inquiry)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ZumBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"crawler\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/extension/email.json",
    "content": "[\n    {\n        \"desc\": \"Airmail\",\n        \"ua\": \"Airmail 1.0 rv:148 (Macintosh; Mac OS X 10.8.3; en_BE)\",\n        \"expect\": {\n            \"name\": \"Airmail\",\n            \"version\": \"1.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Alpine\",\n        \"ua\": \"Alpine/2.21 (Linux; x86_64)\",\n        \"expect\": {\n            \"name\": \"Alpine\",\n            \"version\": \"2.21\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Android Mail (AOSP)\",\n        \"ua\": \"Android/9-email\",\n        \"expect\": {\n            \"name\": \"Android\",\n            \"version\": \"9-email\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Apple Mail\",\n        \"ua\": \"Mail/3826.500.181.1.5 CFNetwork/3826.500.111.1.1 Darwin/24.4.0\",\n        \"expect\": {\n            \"name\": \"Mail\",\n            \"version\": \"3826.500.181.1.5\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Aqua Mail\",\n        \"ua\": \"AquaMail/1.16.0-1081 (build: 101600003)\",\n        \"expect\": {\n            \"name\": \"AquaMail\",\n            \"version\": \"1.16.0-1081\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Balsa\",\n        \"ua\": \"Balsa/2.6.4\",\n        \"expect\": {\n            \"name\": \"Balsa\",\n            \"version\": \"2.6.4\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Barca\",\n        \"ua\": \"Barca/2.8 (Windows NT 5.1)\",\n        \"expect\": {\n            \"name\": \"Barca\",\n            \"version\": \"2.8\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"BlueMail\",\n        \"ua\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) BlueMail/0.10.31 Chrome/61.0.3163.100 Electron/2.0.18 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"BlueMail\",\n            \"version\": \"0.10.31\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"BlueMail (iOS)\",\n        \"ua\": \"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16A405 BlueMail iOS\",\n        \"expect\": {\n            \"name\": \"BlueMail\",\n            \"version\": \"iOS\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Canary Mail\",\n        \"ua\": \"Canary/413 (Macintosh; OS X 14.2.1)\",\n        \"expect\": {\n            \"name\": \"Canary\",\n            \"version\": \"413\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Claws Mail\",\n        \"ua\": \"Claws Mail/3.17.5 (x86_64-pc-linux-gnu)\",\n        \"expect\": {\n            \"name\": \"Claws Mail\",\n            \"version\": \"3.17.5\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"DaumMail\",\n        \"ua\": \"DaumMobileApp (LG-KU5400; U; Android 2.3.7|10; ko-kr) DaumMail/1.0.8 \",\n        \"expect\": {\n            \"name\": \"DaumMail\",\n            \"version\": \"1.0.8\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"eM Client\",\n        \"ua\": \"eMClient/9.2.2157.0\",\n        \"expect\": {\n            \"name\": \"eMClient\",\n            \"version\": \"9.2.2157.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Eudora OSE\",\n        \"ua\": \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.19) Gecko/20110420 Eudora/3.0.4\",\n        \"expect\": {\n            \"name\": \"Eudora\",\n            \"version\": \"3.0.4\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Evolution\",\n        \"ua\": \"Evolution/3.52.3\",\n        \"expect\": {\n            \"name\": \"Evolution\",\n            \"version\": \"3.52.3\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"FairEmail\",\n        \"ua\": \"FairEmail/1.2066 (Android 13; Pixel 7)\",\n        \"expect\": {\n            \"name\": \"FairEmail\",\n            \"version\": \"1.2066\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Foxmail\",\n        \"ua\": \"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 foxmail/7.2.15.80\",\n        \"expect\": {\n            \"name\": \"foxmail\",\n            \"version\": \"7.2.15.80\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Geary\",\n        \"ua\": \"Geary/40.0 (Linux; x86_64)\",\n        \"expect\": {\n            \"name\": \"Geary\",\n            \"version\": \"40.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Gnus\",\n        \"ua\": \"Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)\",\n        \"expect\": {\n            \"name\": \"Gnus\",\n            \"version\": \"5.13\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Horde IMP\",\n        \"ua\": \"Horde::IMP/6.2.27 (Linux)\",\n        \"expect\": {\n            \"name\": \"Horde::IMP\",\n            \"version\": \"6.2.27\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"IBM Notes\",\n        \"ua\": \"Lotus-Notes/8.5.3\",\n        \"expect\": {\n            \"name\": \"Lotus-Notes\",\n            \"version\": \"8.5.3\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"IncrediMail\",\n        \"ua\": \"IncrediMail/6.29.5126\",\n        \"expect\": {\n            \"name\": \"IncrediMail\",\n            \"version\": \"6.29.5126\",\n            \"type\": \"email\"\n        }\n    },\n{\n        \"desc\": \"K-9 Mail\",\n        \"ua\": \"K-9 Mail/5.600\",\n        \"expect\": {\n            \"name\": \"K-9 Mail\",\n            \"version\": \"5.600\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"KMail\",\n        \"ua\": \"KMail/4.14.10 (FreeBSD/12.0-CURRENT; KDE/4.14.10; amd64; ; )\",\n        \"expect\": {\n            \"name\": \"KMail\",\n            \"version\": \"4.14.10\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"KMail2\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kmail2/5.7.3 Safari/534.34\",\n        \"expect\": {\n            \"name\": \"kmail2\",\n            \"version\": \"5.7.3\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Kontact\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kontact/4.13.3 Safari/534.34\",\n        \"expect\": {\n            \"name\": \"kontact\",\n            \"version\": \"4.13.3\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Mailbird\",\n        \"ua\": \"Mailbird/2.9.0.0\",\n        \"expect\": {\n            \"name\": \"Mailbird\",\n            \"version\": \"2.9.0.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"MailMate\",\n        \"ua\": \"MailMate/5663 (Macintosh; Intel Mac OS X 10.15.7)\",\n        \"expect\": {\n            \"name\": \"MailMate\",\n            \"version\": \"5663\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Mailspring\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Mailspring/1.7.8 Chrome/69.0.3497.128 Electron/4.2.12 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"Mailspring\",\n            \"version\": \"1.7.8\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Microsoft Outlook\",\n        \"ua\": \"Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.5431; Pro)\",\n        \"expect\": {\n            \"name\": \"Microsoft Outlook\",\n            \"version\": \"16.0.5431\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Microsoft Outlook for Mac\",\n        \"ua\": \"MacOutlook/14.7.1.161129 (Intel Mac OS X 10.9.6)\",\n        \"expect\": {\n            \"name\": \"MacOutlook\",\n            \"version\": \"14.7.1.161129\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Mutt\",\n        \"ua\": \"Mutt/1.5.21 (2010-09-15)\",\n        \"expect\": {\n            \"name\": \"Mutt\",\n            \"version\": \"1.5.21\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"NaverMailApp\",\n        \"ua\": \"NaverMailApp/2.1.23 (Android 10; SM-N960N)\",\n        \"expect\": {\n            \"name\": \"NaverMailApp\",\n            \"version\": \"2.1.23\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Newton Mail\",\n        \"ua\": \"Newton/10.0.52 (Android 10; K)\",\n        \"expect\": {\n            \"name\": \"Newton\",\n            \"version\": \"10.0.52\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Nine\",\n        \"ua\": \"Nine/4.5.3a\",\n        \"expect\": {\n            \"name\": \"Nine\",\n            \"version\": \"4.5.3a\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Nylas Mail\",\n        \"ua\": \"NylasMail/2.0.32 (Macintosh; OS X 10.12.6)\",\n        \"expect\": {\n            \"name\": \"NylasMail\",\n            \"version\": \"2.0.32\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Outlook Express\",\n        \"ua\": \"Outlook-Express/6.0 (MSIE 6.0; Windows NT 5.1; SV1)\",\n        \"expect\": {\n            \"name\": \"Outlook-Express\",\n            \"version\": \"6.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Pegasus Mail\",\n        \"ua\": \"Pegasus Mail/4.70\",\n        \"expect\": {\n            \"name\": \"Pegasus Mail\",\n            \"version\": \"4.70\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"PocoMail\",\n        \"ua\": \"PocoMail 4.8 (4320) - Licensed Version\",\n        \"expect\": {\n            \"name\": \"PocoMail\",\n            \"version\": \"4.8\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Polymail\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Polymail/2.3.12 Chrome/114.0.5735.134 Electron/25.2.0 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"Polymail\",\n            \"version\": \"2.3.12\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Postbox\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Postbox/7.0.26\",\n        \"expect\": {\n            \"name\": \"Postbox\",\n            \"version\": \"7.0.26\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"ProtonMail\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ProtonMail/1.4.0 Chrome/122.0.6261.156 Electron/29.4.6 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"ProtonMail\",\n            \"version\": \"1.4.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"ProtonMail Bridge\",\n        \"ua\": \"ProtonMail Bridge/3.8.2 (Macintosh; Intel Mac OS X 10_15_7)\",\n        \"expect\": {\n            \"name\": \"ProtonMail Bridge\",\n            \"version\": \"3.8.2\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"R2Mail2\",\n        \"ua\": \"R2Mail2/2.50 (Android)\",\n        \"expect\": {\n            \"name\": \"R2Mail2\",\n            \"version\": \"2.50\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"RainLoop\",\n        \"ua\": \"RainLoop/1.17.0\",\n        \"expect\": {\n            \"name\": \"RainLoop\",\n            \"version\": \"1.17.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Roundcube Webmail\",\n        \"ua\": \"Roundcube Webmail/1.6.0\",\n        \"expect\": {\n            \"name\": \"Roundcube Webmail\",\n            \"version\": \"1.6.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Samsung Email\",\n        \"ua\": \"SamsungEmail/6.1.80.12\",\n        \"expect\": {\n            \"name\": \"SamsungEmail\",\n            \"version\": \"6.1.80.12\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"SparkDesktop\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) SparkDesktop/3.0.30 Chrome/102.0.5005.63 Electron/19.0.4 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"SparkDesktop\",\n            \"version\": \"3.0.30\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Sparrow\",\n        \"ua\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/604.5.6 (KHTML, like Gecko) Sparrow/1043.1\",\n        \"expect\": {\n            \"name\": \"Sparrow\",\n            \"version\": \"1043.1\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Spicebird\",\n        \"ua\": \"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.9pre) Gecko/20100216 Spicebird/0.8\",\n        \"expect\": {\n            \"name\": \"Spicebird\",\n            \"version\": \"0.8\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"SquirrelMail\",\n        \"ua\": \"SquirrelMail/1.4.23 [SVN]\",\n        \"expect\": {\n            \"name\": \"SquirrelMail\",\n            \"version\": \"1.4.23\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Sylpheed\",\n        \"ua\": \"Sylpheed/3.7.0 (MinGW32; Windows NT 6.1; x86_64)\",\n        \"expect\": {\n            \"name\": \"Sylpheed\",\n            \"version\": \"3.7.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"The Bat!\",\n        \"ua\": \"The Bat! 9.2.1\",\n        \"expect\": {\n            \"name\": \"The Bat!\",\n            \"version\": \"9.2.1\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Thunderbird\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0\",\n        \"expect\": {\n            \"name\": \"Thunderbird\",\n            \"version\": \"78.13.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Trojita\",\n        \"ua\": \"Trojita/0.7\",\n        \"expect\": {\n            \"name\": \"Trojita\",\n            \"version\": \"0.7\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Turnpike\",\n        \"ua\": \"Turnpike/6.07-U\",\n        \"expect\": {\n            \"name\": \"Turnpike\",\n            \"version\": \"6.07-U\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Tuta Desktop (Tutanota)\",\n        \"ua\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) tutanota-desktop/3.110.1 Chrome/110.0.5481.179 Electron/23.1.3 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"tutanota-desktop\",\n            \"version\": \"3.110.1\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Wanderlust\",\n        \"ua\": \"Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (Gojō) APEL/10.8 Emacs/23.1 (i486-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO)\",\n        \"expect\": {\n            \"name\": \"Wanderlust\",\n            \"version\": \"2.15.9\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Windows Live Mail\",\n        \"ua\": \"Windows-Live-Mail/15.4.3508.1109\",\n        \"expect\": {\n            \"name\": \"Windows-Live-Mail\",\n            \"version\": \"15.4.3508.1109\",\n            \"type\": \"email\"\n        }\n    },\n{\n        \"desc\": \"Yahoo! Mail (Android)\",\n        \"ua\": \"YahooMobile/1.0 (mail; 3.0.5.1311380); (Linux; U; Android 4.0.3; htc_runnymede Build/ICE_CREAM_SANDWICH_MR1);\",\n        \"expect\": {\n            \"name\": \"Yahoo Mail\",\n            \"version\": \"1.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Yahoo! Mail (Legacy)\",\n        \"ua\": \"YahooMobileMail/1.0 (Android Mail; 1.3.10) (supersonic;HTC;PC36100;2.3.5/GRJ90) \",\n        \"expect\": {\n            \"name\": \"Yahoo Mail\",\n            \"version\": \"1.3.10\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Yahoo! Mail (iOS)\",\n        \"ua\": \"YahooMail/1.0 (iOS; 1.0.0; en_US)\",\n        \"expect\": {\n            \"name\": \"Yahoo Mail\",\n            \"version\": \"1.0\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Zimbra\",\n        \"ua\": \"Mozilla/5.0 (Windows; U; Windows NT 6.2; it; rv:1.9.2.19pre) Gecko/20110902 Prism zdesktop/7.2.8\",\n        \"expect\": {\n            \"name\": \"Zimbra\",\n            \"version\": \"7.2.8\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"Zimbra (Server)\",\n        \"ua\": \"Zimbra/9.0.0_GA_4138\",\n        \"expect\": {\n            \"name\": \"Zimbra\",\n            \"version\": \"9.0.0_GA_4138\",\n            \"type\": \"email\"\n        }\n    },\n    {\n        \"desc\": \"ZohoMail\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ZohoMail-Desktop/1.6.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36\",\n        \"expect\": {\n            \"name\": \"ZohoMail-Desktop\",\n            \"version\": \"1.6.3\",\n            \"type\": \"email\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/extension/extra-devices.json",
    "content": "[{\n    \"desc\": \"Essential PH-1\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 9; PH-1 Build/PPR1.180905.036) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.86 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Essential\",\n        \"model\": \"PH-1\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"Gigaset Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; Gigaset QV830 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Gigaset\",\n        \"model\": \"QV830\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"RCA Voyager III Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; RCT6973W43 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"RCA\",\n        \"model\": \"RCT6973W43\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"RCA Voyager II Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.0; RCT6773W22B Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"RCA\",\n        \"model\": \"RCT6773W22B\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Verizon Quanta Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; QMV7B Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Verizon\",\n        \"model\": \"QMV7B\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Verizon Ellipsis 8 Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; QTAQZ3 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Verizon\",\n        \"model\": \"QTAQZ3\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Verizon Ellipsis 8HD Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; QTASUN1 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Verizon\",\n        \"model\": \"QTASUN1\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Dell Venue 8 Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Venue 8 3830 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Dell\",\n        \"model\": \"Venue 8 3830\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Dell Venue 7 Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Venue 7 3730 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Dell\",\n        \"model\": \"Venue 7 3730\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Barnes & Noble Nook HD+ Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; Barnes & Noble Nook HD+ Build/JZO54K; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n    \"expect\": {\n        \"vendor\": \"Barnes & Noble\",\n        \"model\": \"Nook HD+\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Barnes & Noble V400 Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Barnes & Noble\",\n        \"model\": \"V400\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"NuVision TM101A540N Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.1; TM101A540N Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/50.0.2661.86 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"NuVision\",\n        \"model\": \"TM101A540N\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"ZTE-Z431\",\n    \"ua\": \"ZTE-Z431/1.4.0 NetFront/4.2 QTV5.1 Profile/MIDP-2.1 Configuration/CLDC-1.1\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"Z431\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"ZTE\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; ZTE-Z740G Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"Z740G\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"ZTE K Series Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 6.0.1; K88 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"K88\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"ZTE Nubia Red Magic 3\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 9; NX629J Build/PKQ1.190321.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/45016 Mobile Safari/537.36 MMWEBID/4064 MicroMessenger/7.0.10.1580(0x27000A34) Process/tools NetType/WIFI Language/zh_CN ABI/arm64\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"NX629J\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"ZTE Blade A5\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 9; ZTE Blade A5 2019) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"Blade A5 2019\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"ZTE BLADE V0730\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 6.0; ZTE BLADE V0730) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"BLADE V0730\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"ZTE B2017G\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 7.1.1; ZTE B2017G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.93 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"ZTE\",\n        \"model\": \"B2017G\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"Swizz GEN610\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; GEN610 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Swiss\",\n        \"model\": \"GEN610\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"Swizz ZUR700\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; ZUR700 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Swiss\",\n        \"model\": \"ZUR700\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Zeki TB782b Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.4; en-US; TB782B Build/IMM76D) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.0.2.299 U3/0.8.0 Mobile Safari/534.31\",\n    \"expect\": {\n        \"vendor\": \"Zeki\",\n        \"model\": \"TB782B\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Dragon Touch Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.0.4; DT9138B Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Dragon Touch\",\n        \"model\": \"9138B\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Insignia Tablet\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 6.0.1; NS-P08A7100 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Insignia\",\n        \"model\": \"NS-P08A7100\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Voice Xtreme V75\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.2.1; en-us; V75 Build/JOP40D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\",\n    \"expect\": {\n        \"vendor\": \"Voice\",\n        \"model\": \"V75\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"LvTel V11\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.1.1; V11 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"LvTel\",\n        \"model\": \"V11\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"Envizen Tablet V100MD\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; V100MD Build/V100MD.20130816) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30\",\n    \"expect\": {\n        \"vendor\": \"Envizen\",\n        \"model\": \"V100MD\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Rotor Tablet\",\n    \"ua\": \"mozilla/5.0 (linux; android 5.0.1; tu_1491 build/lrx22c) applewebkit/537.36 (khtml, like gecko) chrome/43.0.2357.93 safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Rotor\",\n        \"model\": \"1491\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"MachSpeed Tablets\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; Trio 7.85 vQ Build/Trio_7.85_vQ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"MachSpeed\",\n        \"model\": \"Trio 7.85 vQ\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Trinity Tablets\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.1; Trinity T101 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Trinity\",\n        \"model\": \"T101\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"NextBook Next7\",\n    \"ua\": \"Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Next7P12 Build/IMM76I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30\",\n    \"expect\": {\n        \"vendor\": \"NextBook\",\n        \"model\": \"Next7P12\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"NextBook Tablets\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.0; NXA8QC116 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"NextBook\",\n        \"model\": \"NXA8QC116\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Le Pan Tablets\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Le Pan\",\n        \"model\": \"TC802A\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Le Pan Tablets\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Le Pan\",\n        \"model\": \"TC802A\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"AT&T Radiant Core U304AA\",\n    \"ua\": \"Dalvik/2.1.0 (Linux; U; Android 9; U304AA Build/P00610)\",\n    \"expect\": {\n        \"vendor\": \"AT&T\",\n        \"model\": \"U304AA\",\n        \"type\": \"mobile\"\n    }\n},\n{\n    \"desc\": \"Vodafone Smart Tab 4G\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.4; Vodafone Smart Tab 4G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Vodafone\",\n        \"model\": \"Smart Tab 4G\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"Vodafone Smart ultra 6\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 5.0.2; Vodafone Smart ultra 6 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36\",\n    \"expect\": {\n        \"vendor\": \"Vodafone\",\n        \"model\": \"Smart ultra 6\",\n        \"type\": \"tablet\"\n    }\n},\n{\n    \"desc\": \"4ife 4K Smart TV Box\",\n    \"ua\": \"Mozilla/5.0 (Linux; Android 4.4.2; 4ife 4K Smart TV Box Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 Vinebre\",\n    \"expect\": {\n        \"vendor\": \"undefined\",\n        \"model\": \"undefined\",\n        \"type\": \"smarttv\"\n    }\n}]"
  },
  {
    "path": "test/data/ua/extension/fetcher.json",
    "content": "[\n    {\n        \"desc\"    : \"AhrefsSiteAudit\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.128 Mobile Safari/537.36 (compatible; AhrefsSiteAudit/6.1; +http://ahrefs.com/robot/site-audit)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AhrefsSiteAudit\",\n            \"version\" : \"6.1\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Asana\",\n        \"ua\"      : \"Asana/1.4.0 WebsiteMetadataRetriever\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Asana\",\n            \"version\" : \"1.4.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Better Uptime Bot\",\n        \"ua\"      : \"Better Uptime Bot Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Better Uptime Bot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"BingPreview\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BingPreview\",\n            \"version\" : \"1.0b\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Bit.ly\",\n        \"ua\"      : \"bitlybot/3.0 (+http://bit.ly/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"bitlybot\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Blueno\",\n        \"ua\"      : \"facebookexternalhit/1.1 (compatible; Blueno/1.0; +http://naver.me/scrap)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Blueno\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Bluesky\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app) Chrome/100.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bluesky\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"BufferLinkPreviewBot\",\n        \"ua\"      : \"BufferLinkPreviewBot/1.0 (+https://scraper.buffer.com/about/bots/link-preview-bot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BufferLinkPreviewBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"ChatGPT-User\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ChatGPT-User\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Chrome-Lighthouse\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4590.2 Mobile Safari/537.36 Chrome-Lighthouse\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Lighthouse\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Claude-User\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Claude-User/1.0; +Claude-User@anthropic.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Claude-User\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Cohere-AI\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Cohere-AI/1.0; +https://cohere.com/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Cohere-AI\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Discordbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Discordbot\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"DuckAssistBot\",\n        \"ua\"      : \"DuckAssistBot/1.2; (+http://duckduckgo.com/duckassistbot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DuckAssistBot\",\n            \"version\" : \"1.2\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Feedly\",\n        \"ua\"      : \"Feedly/1.0 (+http://www.feedly.com/fetcher.html; 1 subscribers; like FeedFetcher-Google)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Feedly\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Feedly\",\n        \"ua\"      : \"FeedlyBot/1.0 (http://feedly.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Feedly\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"FlipboardProxy\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0 (FlipboardProxy/1.2; +http://flipboard.com/browserproxy)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"FlipboardProxy\",\n            \"version\" : \"1.2\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Gemini-Deep-Research\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Gemini-Deep-Research; +https://gemini.google/overview/deep-research/) Chrome/135.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Gemini-Deep-Research\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Docs\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; GoogleDocs; apps-spreadsheets; +http://docs.google.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoogleDocs\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google FeedFetcher\",\n        \"ua\"      : \"FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"FeedFetcher-Google\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Image Proxy\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoogleImageProxy\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Read Aloud - Mobile agent\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36 (compatible; Google-Read-Aloud; +https://support.google.com/webmasters/answer/1061943)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-Read-Aloud\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Read Aloud - Desktop agent\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 (compatible; Google-Read-Aloud; +https://support.google.com/webmasters/answer/1061943)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-Read-Aloud\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Page Renderer\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 Google-PageRenderer Google (+https://developers.google.com/+/web/snippet/) \",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-PageRenderer\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Publisher Center\",\n        \"ua\"      : \"GoogleProducer; (+https://developers.google.com/search/docs/crawling-indexing/google-producer)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GoogleProducer\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Google Site Verifier\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Google-Site-Verification/1.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Google-Site-Verification\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"HubSpot Page Fetcher\",\n        \"ua\"      : \"HubSpot Page Fetcher/1.0 http://www.hubspot.com/ web-crawlers@hubspot.com\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HubSpot Page Fetcher\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Iframely\",\n        \"ua\"      : \"Iframely/1.3.1 (+https://iframely.com/docs/about)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Iframely\",\n            \"version\" : \"1.3.1\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"kakaotalk-scrap\",\n        \"ua\"      : \"facebookexternalhit/1.1; kakaotalk-scrap/1.0; +https://devtalk.kakao.com/t/scrap/33984\",\n        \"expect\"  :\n        {\n            \"name\"    : \"kakaotalk-scrap\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"KeybaseBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; KeybaseBot; +https://keybase.io)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"KeybaseBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Meta-ExternalFetcher\",\n        \"ua\"      : \"meta-externalfetcher/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"meta-externalfetcher\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"MicrosoftPreview\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; MicrosoftPreview/2.0; +https://aka.ms/MicrosoftPreview) Chrome/W.X.Y.Z Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MicrosoftPreview\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"MistralAI-User\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; MistralAI-User/1.0; +https://docs.mistral.ai/robots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MistralAI-User\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"NovaAct\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Agent-NovaAct/0.9\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NovaAct\",\n            \"version\" : \"0.9\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Perplexity-User\",\n        \"ua\"      : \"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Perplexity-User/1.0; +https://perplexity.ai/perplexity-user)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Perplexity-User\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Pinterestbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Pinterestbot/1.0; +http://www.pinterest.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Pinterestbot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Rogerbot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; rogerBot/1.0; UrlCrawler; http://www.seomoz.org/dp/rogerbot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"rogerBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"SiteAuditBot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; SiteAuditBot/0.97; +http://www.semrush.com/bot.html)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SiteAuditBot\",\n            \"version\" : \"0.97\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Slack-ImgProxy\",\n        \"ua\"      : \"Slack-ImgProxy 0.19 (+https://api.slack.com/robots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Slack-ImgProxy\",\n            \"version\" : \"0.19\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Slackbot\",\n        \"ua\"      : \"Slackbot 1.0 (+https://api.slack.com/robots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Slackbot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Slackbot-LinkExpanding\",\n        \"ua\"      : \"Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Slackbot-LinkExpanding\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Snap URL Preview\",\n        \"ua\"      : \"Snap URL Preview Service; bot; snapchat; https://developers.snap.com/robots  \",\n        \"expect\"  :\n        {\n            \"name\"    : \"Snap URL Preview\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"SkypeUriPreview\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) SkypeUriPreview Preview/0.5 skype-url-preview@microsoft.com\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SkypeUriPreview\",\n            \"version\" : \"0.5\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"TelegramBot\",\n        \"ua\"      : \"TelegramBot (like TwitterBot)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"TelegramBot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Twitterbot\",\n        \"ua\"      : \"Twitterbot/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Twitterbot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"UptimeBot\",\n        \"ua\"      : \"UptimeBot/1.0 EU-1 (+https://uptime.bot/hello)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UptimeBot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"UptimeRobot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"UptimeRobot\",\n            \"version\" : \"2.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"vercel-favicon-bot\",\n        \"ua\"      : \"vercel-favicon-bot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"vercel-favicon-bot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"vercel-screenshot-bot\",\n        \"ua\"      : \"vercel-screenshot-bot\",\n        \"expect\"  :\n        {\n            \"name\"    : \"vercel-screenshot-bot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Vercelbot\",\n        \"ua\"      : \"Vercelbot (+https://vercel.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Vercelbot\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"vercelflags\",\n        \"ua\"      : \"vercelflags\",\n        \"expect\"  :\n        {\n            \"name\"    : \"vercelflags\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"verceltracing\",\n        \"ua\"      : \"verceltracing\",\n        \"expect\"  :\n        {\n            \"name\"    : \"verceltracing\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"VirusTotal\",\n        \"ua\"      : \"AppEngine-Google; (+http://code.google.com/appengine; appid: s~virustotalcloud)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"virustotal\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"WhatsApp\",\n        \"ua\"      : \"WhatsApp/2.23.20.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"WhatsApp\",\n            \"version\" : \"2.23.20.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YaDirectFetcher\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YaDirectFetcher/1.0; Dyatel; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YaDirectFetcher\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexCalendar\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexCalendar/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexCalendar\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexDirect\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexDirect/3.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexDirect\",\n            \"version\" : \"3.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexDirectDyn\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexDirectDyn/1.0; +http://yandex.com/bots\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexDirectDyn\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexForDomain\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexForDomain/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexForDomain\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexPagechecker\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexPagechecker/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexPagechecker\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexSearchShop\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexSearchShop/1.0; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexSearchShop\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexSitelinks\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexSitelinks; Dyatel; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexSitelinks\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"YandexUserproxy\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; YandexUserproxy; robot; +http://yandex.com/bots)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"YandexUserproxy\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"fetcher\"\n        }\n    },\n    {\n        \"desc\"    : \"Zoombot\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Zoombot/1.0; +https://zoom.us; crawler@domain.com)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Zoombot\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"fetcher\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/extension/inapp.json",
    "content": "[\n    {\n        \"desc\"    : \"Discord on Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.26 Chrome/108.0.5359.215 Electron/22.3.2 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"discord\",\n            \"version\" : \"0.0.26\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Discord on iPad\",\n        \"ua\"      : \"Discord/52.0 (iPad; iOS 14.4; Scale/2.00)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Discord\",\n            \"version\" : \"52.0\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Evernote on Windows\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Evernote Windows/306387 (pt-PT, DDL); Windows/6.1.0 (Win32); Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Evernote\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Figma on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_4_0) AppleWebKit/537.36 (KHTML, like Gecko) Figma/99.0.0 Chrome/89.0.4389.128 Electron/12.0.9 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Figma\",\n            \"version\" : \"99.0.0\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Flipboard on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.0.0; SM-A720F Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36 Flipboard/4.1.13/4342,4.1.13.4342\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Flipboard\",\n            \"version\" : \"4.1.13\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Mattermost on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Mattermost/4.4.0 Chrome/76.0.3809.146 Electron/6.1.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mattermost\",\n            \"version\" : \"4.4.0\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Mattermost on iPad\",\n        \"ua\"      : \"Mattermost/1.49.1 (iPad; iOS 15.3.1; Scale/2.00)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mattermost\",\n            \"version\" : \"1.49.1\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Teams on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Teams/1.8.00.3758 Chrome/126.0.6478.261 Electron/31.7.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Teams\",\n            \"version\" : \"1.8.00.3758\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Teams on iPad\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU OS 16_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 TeamsMobile-iOS\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Teams\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Teams on iPhone\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 TeamsMobile-iOS\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Teams\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Microsoft Teams on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.1.0; SM-G610F Build/M1AJQ; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36 TeamsMobile-Android\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Teams\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Notion on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Notion/2.0.23 Chrome/91.0.4472.164 Electron/13.6.9 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Notion\",\n            \"version\" : \"2.0.23\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Postman on Mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Postman/9.29.0 Chrome/94.0.4606.81 Electron/15.5.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Postman\",\n            \"version\" : \"9.29.0\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Rambox on mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Rambox/0.7.7 Chrome/78.0.3904.130 Electron/7.2.4 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Rambox\",\n            \"version\" : \"0.7.7\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Rocket.Chat on mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Rocket.Chat/3.8.16 Chrome/106.0.5249.199 Electron/21.3.3 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Rocket.Chat\",\n            \"version\" : \"3.8.16\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Slack on mac\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Slack/4.39.90 Chrome/127.0.6533.72 Electron/13.1.9 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Slack\",\n            \"version\" : \"4.39.90\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"TikTok Lite\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 8.0.0; SM-J400F Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36 Channel/release AppName/ultralite app_version/27.2.3 Region/ID ByteLocale/id-ID ByteFullLocale/id-ID\",\n        \"expect\"  :\n        {\n            \"name\"    : \"TikTok Lite\",\n            \"version\" : \"27.2.3\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"VS Code on Windows\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.85.1 Chrome/114.0.5735.289 Electron/25.9.7 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"VS Code\",\n            \"version\" : \"1.85.1\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Yahoo! Japan on Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 13; SH-M20 Build/TKQ1.220915.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.163 Mobile Safari/537.36 YJApp-ANDROID jp.co.yahoo.android.yjtop/3.187.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yahoo! Japan\",\n            \"version\" : \"3.187.0\",\n            \"type\"    : \"inapp\"\n        }\n    },\n    {\n        \"desc\"    : \"Yahoo! Japan on iOS\",\n        \"ua\"      : \"Mozilla/5.0 (iPad; CPU OS 18_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 YJApp-IOS jp.co.yahoo.ipn.appli/4.131.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Yahoo! Japan\",\n            \"version\" : \"4.131.0\",\n            \"type\"    : \"inapp\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/extension/library.json",
    "content": "[\n    {\n        \"desc\"    : \"AdobeAIR\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/3.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AdobeAIR\",\n            \"version\" : \"3.1\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"aiohttp\",\n        \"ua\"      : \"Python/3.9 aiohttp/3.8.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"aiohttp\",\n            \"version\" : \"3.8.1\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Apache-HttpClient\",\n        \"ua\"      : \"Apache-HttpClient/4.5.14 (Java/17.0.12)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Apache-HttpClient\",\n            \"version\" : \"4.5.14\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Axios\",\n        \"ua\"      : \"axios/1.7.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"axios\",\n            \"version\" : \"1.7.2\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Bun\",\n        \"ua\"      : \"Bun/1.0.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bun\",\n            \"version\" : \"1.0.6\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Dart\",\n        \"ua\"      : \"Dart/3.5 (dart:io)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Dart\",\n            \"version\" : \"3.5\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Deno\",\n        \"ua\"      : \"Deno/2.1.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Deno\",\n            \"version\" : \"2.1.7\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"go-http-client\",\n        \"ua\"      : \"go-http-client/1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"go-http-client\",\n            \"version\" : \"1.1\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"got\",\n        \"ua\"      : \"got/9.6.0 (https://github.com/sindresorhus/got)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"got\",\n            \"version\" : \"9.6.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"GuzzleHttp\",\n        \"ua\"      : \"GuzzleHttp/6.5.5 curl/7.70.0 PHP/7.4.22\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GuzzleHttp\",\n            \"version\" : \"6.5.5\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"hackney\",\n        \"ua\"      : \"hackney/1.20.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"hackney\",\n            \"version\" : \"1.20.1\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"http.rb\",\n        \"ua\"      : \"http.rb/4.2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"http.rb\",\n            \"version\" : \"4.2.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Java\",\n        \"ua\"      : \"Java/1.6.0_14\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Java\",\n            \"version\" : \"1.6.0_14\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Java HTTPClient\",\n        \"ua\"      : \"Java-http-client/11.0.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Java-http-client\",\n            \"version\" : \"11.0.6\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Jetty\",\n        \"ua\"      : \"Jetty/11.0.13\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Jetty\",\n            \"version\" : \"11.0.13\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"jsdom\",\n        \"ua\"      : \"Mozilla/5.0 (unknown OS) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"jsdom\",\n            \"version\" : \"11.12.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"libwww-perl\",\n        \"ua\"      : \"libwww-perl/6.05\",\n        \"expect\"  :\n        {\n            \"name\"    : \"libwww-perl\",\n            \"version\" : \"6.05\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"lua-resty-http\",\n        \"ua\"      : \"lua-resty-http/0.07 (Lua)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"lua-resty-http\",\n            \"version\" : \"0.07\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Needle\",\n        \"ua\"      : \"Needle/3.2.0 (Node.js v18.14.2; win32 x64)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Needle\",\n            \"version\" : \"3.2.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Node.js\",\n        \"ua\"      : \"Node.js/22\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Node.js\",\n            \"version\" : \"22\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"node-fetch\",\n        \"ua\"      : \"node-fetch/1.0 (+https://github.com/bitinn/node-fetch)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"node-fetch\",\n            \"version\" : \"1.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Nutch\",\n        \"ua\"      : \"AliyunSecBot/Nutch-1.21-SNAPSHOT\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Nutch\",\n            \"version\" : \"1.21-SNAPSHOT\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"ocaml-cohttp\",\n        \"ua\"      : \"ocaml-cohttp/1.2.00\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ocaml-cohttp\",\n            \"version\" : \"1.2.00\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"OkHttp\",\n        \"ua\"      : \"okhttp/3.2.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"okhttp\",\n            \"version\" : \"3.2.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"PHPCrawl\",\n        \"ua\"      : \"phpcrawl\",\n        \"expect\"  :\n        {\n            \"name\"    : \"phpcrawl\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"PHP-SOAP\",\n        \"ua\"      : \"PHP-SOAP/7.4.33\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PHP-SOAP\",\n            \"version\" : \"7.4.33\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"PostmanRuntime\",\n        \"ua\"      : \"PostmanRuntime/7.26.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PostmanRuntime\",\n            \"version\" : \"7.26.5\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Python httpx\",\n        \"ua\"      : \"python-httpx/0.27.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"python-httpx\",\n            \"version\" : \"0.27.2\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Python urllib\",\n        \"ua\"      : \"Python-urllib/2.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Python-urllib\",\n            \"version\" : \"2.6\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Python urllib3\",\n        \"ua\"      : \"python-urllib3/1.26.18\",\n        \"expect\"  :\n        {\n            \"name\"    : \"python-urllib3\",\n            \"version\" : \"1.26.18\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Python requests\",\n        \"ua\"      : \"python-requests/2.32\",\n        \"expect\"  :\n        {\n            \"name\"    : \"python-requests\",\n            \"version\" : \"2.32\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"rest-client\",\n        \"ua\"      : \"rest-client/2.1.0 (linux-gnu x86_64) ruby/2.7.2p137\",\n        \"expect\"  :\n        {\n            \"name\"    : \"rest-client\",\n            \"version\" : \"2.1.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"Scrapy\",\n        \"ua\"      : \"Scrapy/1.5.0 (+https://scrapy.org)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Scrapy\",\n            \"version\" : \"1.5.0\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"superagent\",\n        \"ua\"      : \"node-superagent/5.0.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"node-superagent\",\n            \"version\" : \"5.0.2\",\n            \"type\"    : \"library\"\n        }\n    },\n    {\n        \"desc\"    : \"undici\",\n        \"ua\"      : \"undici\",\n        \"expect\"  :\n        {\n            \"name\"    : \"undici\",\n            \"version\" : \"undefined\",\n            \"type\"    : \"library\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/extension/mediaplayer.json",
    "content": "[\n    {\n        \"desc\"    : \"Coremedia\",\n        \"ua\"      : \"Apple Mac OS X v10.6.4 CoreMedia v1.0.0.10F2108\",\n        \"expect\"  : \n        {\n            \"name\"    : \"CoreMedia\",\n            \"version\" : \"1.0.0.10F2108\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"AppleCoreMedia\",\n        \"ua\"      : \"AppleCoreMedia/1.0.0.10A403 (iPad; U; CPU OS 6_0 like Mac OS X; it_it)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"AppleCoreMedia\",\n            \"version\" : \"1.0.0.10A403\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"AppleTv\",\n        \"ua\"      : \"AppleTV/3.0.2 (Macintosh; Intel Mac OS X 10.4.7) AppleWebKit/528.18\",\n        \"expect\"  : \n        {\n            \"name\"    : \"AppleTV\",\n            \"version\" : \"3.0.2\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Aqualung\",\n        \"ua\"      : \"Aqualung/R-1114\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Aqualung\",\n            \"version\" : \"R-1114\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Ares\",\n        \"ua\"      : \"Ares 2.2.4.3048\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Ares\",\n            \"version\" : \"2.2.4.3048\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Audacious\",\n        \"ua\"      : \"Audacious/3.2.2 neon/0.29.3\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Audacious\",\n            \"version\" : \"3.2.2\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"AudiMusicStream\",\n        \"ua\"      : \"AudiMusicStream/3020.130826151911\",\n        \"expect\"  : \n        {\n            \"name\"    : \"AudiMusicStream\",\n            \"version\" : \"3020.130826151911\",\n            \"major\"   : \"3020\"\n        }\n    },\n    {\n        \"desc\"    : \"BASS\",\n        \"ua\"      : \"BASS/2.4\",\n        \"expect\"  : \n        {\n            \"name\"    : \"BASS\",\n            \"version\" : \"2.4\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"BSPlayer\",\n        \"ua\"      : \"BSPlayer/2\",\n        \"expect\"  : \n        {\n            \"name\"    : \"BSPlayer\",\n            \"version\" : \"2\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Core\",\n        \"ua\"      : \"CORE/6.506.4.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"CORE\",\n            \"version\" : \"6.506.4.1\",\n            \"major\"   : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Clementine\",\n        \"ua\"      : \"Clementine 1.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Clementine\",\n            \"version\" : \"1.1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"NexPlayer\",\n        \"ua\"      : \"E97510d/ Player/NexPlayer 4.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"NexPlayer\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"FLRP\",\n        \"ua\"      : \"FLRP/2.5 CFNetwork/609.1.4 Darwin/13.0.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Flip Player\",\n            \"version\" : \"2.5\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"FStream\",\n        \"ua\"      : \"FStream\",\n        \"expect\"  : \n        {\n            \"name\"    : \"FStream\",\n            \"version\" : \"undefined\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"GStreamer\",\n        \"ua\"      : \"GStreamer souphttpsrc (compatible; LG NetCast.TV-2012) libsoup/2.34.2\",\n        \"expect\"  : \n        {\n            \"name\"    : \"GStreamer\",\n            \"version\" : \"2.34.2\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"GnomeMplayer\",\n        \"ua\"      : \"GnomeMplayer/1.0.2\",\n        \"expect\"  : \n        {\n            \"name\"    : \"GnomeMplayer\",\n            \"version\" : \"1.0.2\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"HTC Streaming Player\",\n        \"ua\"      : \"HTC Streaming Player htc_asia_wwe / 1.0 / endeavoru / 4.1.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"HTC Streaming Player\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"HTC One S\",\n        \"ua\"      : \"HTC_One_S/3.16.111.10\",\n        \"expect\"  : \n        {\n            \"name\"    : \"HTC One S\",\n            \"version\" : \"3.16.111.10\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"LG Player\",\n        \"ua\"      : \"LG Player 1.0; Android\",\n        \"expect\"  : \n        {\n            \"name\"    : \"LG Player\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"NexPlayer\",\n        \"ua\"      : \"LG-P700/V10k-DEC-12-2012 Player/NexPlayer 4.0 for Android\",\n        \"expect\"  : \n        {\n            \"name\"    : \"NexPlayer\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"LG Player\",\n        \"ua\"      : \"LGE400/V10b Player/LG Player 1.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"LG Player\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Lavf\",\n        \"ua\"      : \"Lavf52.111.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Lavf\",\n            \"version\" : \"52.111.0\",\n            \"major\"   : \"52\"\n        }\n    },\n    {\n        \"desc\"    : \"Lyssna\",\n        \"ua\"      : \"Lyssna/46 CFNetwork/609.1.4 Darwin/13.0.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Lyssna\",\n            \"version\" : \"46\",\n            \"major\"   : \"46\"\n        }\n    },\n    {\n        \"desc\"    : \"MPlayer\",\n        \"ua\"      : \"MPlayer 1.1-4.2.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"MPlayer\",\n            \"version\" : \"1.1-4.2.1\",\n            \"major\"   : \"\"\n        }\n    },\n    {\n        \"desc\"    : \"MPlayer SVN\",\n        \"ua\"      : \"MPlayer SVN-r33713-4.6.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"MPlayer\",\n            \"version\" : \"r33713-4.6.1\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"MPlayer ubuntu\",\n        \"ua\"      : \"MPlayer svn r34540 (Ubuntu), built with gcc-4.6\",\n        \"expect\"  : \n        {\n            \"name\"    : \"MPlayer\",\n            \"version\" : \"r34540\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"MoC\",\n        \"ua\"      : \"Music On Console/2.5.0-beta1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Music On Console\",\n            \"version\" : \"2.5.0-beta1\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"MPD\",\n        \"ua\"      : \"Music Player Daemon 0.17.4\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Music Player Daemon\",\n            \"version\" : \"0.17.4\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"NSPlayer\",\n        \"ua\"      : \"NSPlayer/11.0.5358.4827 WMFSDK/11.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"NSPlayer\",\n            \"version\" : \"11.0.5358.4827\",\n            \"major\"   : \"11\"\n        }\n    },\n    {\n        \"desc\"    : \"Nero Home\",\n        \"ua\"      : \"Nero Home/1.5.3.0 (compatible; Nero AG; Nero Home 1.5.3.0)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Nero Home\",\n            \"version\" : \"1.5.3.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"NexPlayer\",\n        \"ua\"      : \"NexPlayer 4.0 for Android( stagefright alternative )\",\n        \"expect\"  : \n        {\n            \"name\"    : \"NexPlayer\",\n            \"version\" : \"4.0\",\n            \"major\"   : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia3xx\",\n        \"ua\"      : \"Nokia303/14.87 CLDC-1.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Nokia303\",\n            \"version\" : \"14.87\",\n            \"major\"   : \"14\"\n        }\n    },\n    {\n        \"desc\"    : \"MPlayer SVN Sherpya\",\n        \"ua\"      : \"MPlayer Sherpya-SVN-r33124-4.2.5\",\n        \"expect\"  : \n        {\n            \"name\"    : \"MPlayer\",\n            \"version\" : \"r33124-4.2.5\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Philips Songbird\",\n        \"ua\"      : \"NotMoz/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.2.3) Gecko/20101207 Philips-Songbird/5.4.1980 Songbird/1.9.4 (20110302030555)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Songbird\",\n            \"version\" : \"1.9.4\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Ossproxy\",\n        \"ua\"      : \"OSSProxy 1.3.336.320 (Build 336.320 Win32 en-us)(Aug 16 2013 17:38:43)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"OSSProxy\",\n            \"version\" : \"1.3.336.320\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Winamp3\",\n        \"ua\"      : \"Nullsoft Winamp3 version 3.0 (compatible)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Winamp\",\n            \"version\" : \"3.0\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"PSP\",\n        \"ua\"      : \"PSP-InternetRadioPlayer/1.00\",\n        \"expect\"  : \n        {\n            \"name\"    : \"PSP-InternetRadioPlayer\",\n            \"version\" : \"1.00\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"urllib\",\n        \"ua\"      : \"Python-urllib/2.7\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Python-urllib\",\n            \"version\" : \"2.7\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"QuickTime\",\n        \"ua\"      : \"QuickTime/7.5.6 (qtver=7.5.6;cpu=IA32;os=Mac 10.5.8)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"QuickTime\",\n            \"version\" : \"7.5.6\",\n            \"major\"   : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"RMA\",\n        \"ua\"      : \"RMA/1.0 (compatible; RealMedia)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"RMA\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"RadioApp\",\n        \"ua\"      : \"RadioApp/1.0 CFNetwork/609.1.4 Darwin/11.4.2\",\n        \"expect\"  : \n        {\n            \"name\"    : \"RadioApp\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"RadioClientApplication\",\n        \"ua\"      : \"RadioClientApplication/20 CFNetwork/609.1.4 Darwin/13.0.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"RadioClientApplication\",\n            \"version\" : \"20\",\n            \"major\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"stagefright\",\n        \"ua\"      : \"Samsung GT-I9070 stagefright/1.1 (Linux;Android 2.3.6)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"stagefright\",\n            \"version\" : \"1.1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Soundtap\",\n        \"ua\"      : \"Soundtap/1.2.4 CFNetwork/672.0.2 Darwin/14.0.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Soundtap\",\n            \"version\" : \"1.2.4\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Streamium\",\n        \"ua\"      : \"Streamium/1.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Streamium\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"Totem\",\n        \"ua\"      : \"Totem/3.0.1\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Totem\",\n            \"version\" : \"3.0.1\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"VLC\",\n        \"ua\"      : \"VLC media player - version 0.8.6c Janus - (c) 1996-2007 the VideoLAN team\",\n        \"expect\"  : \n        {\n            \"name\"    : \"VLC\",\n            \"version\" : \"0.8.6c\",\n            \"major\"   : \"0\"\n        }\n    },\n    {\n        \"desc\"    : \"VLC\",\n        \"ua\"      : \"VLC/2.0.0 LibVLC/2.0.0\",\n        \"expect\"  : \n        {\n            \"name\"    : \"VLC\",\n            \"version\" : \"2.0.0\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Videos\",\n        \"ua\"      : \"Videos/3.8.2\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Video\",\n            \"version\" : \"3.8.2\",\n            \"major\"   : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Winamp\",\n        \"ua\"      : \"Winamp 2.81\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Winamp\",\n            \"version\" : \"2.81\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Winamp\",\n        \"ua\"      : \"WinampMPEG/2.00\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Winamp\",\n            \"version\" : \"2.00\",\n            \"major\"   : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Media Player\",\n        \"ua\"      : \"Windows-Media-Player/10.00.00.4019\",\n        \"expect\"  : \n        {\n            \"name\"    : \"Windows Media Player\",\n            \"version\" : \"10.00.00.4019\",\n            \"major\"   : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"XBMC\",\n        \"ua\"      : \"XBMC/12.0 Git:20130127-fb595f2 (Windows NT 6.1;WOW64;Win64;x64; http://www.xbmc.org)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"XBMC\",\n            \"version\" : \"12.0\",\n            \"major\"   : \"12\"\n        }\n    },\n    {\n        \"desc\"    : \"rad.io\",\n        \"ua\"      : \"rad.io 1.18.1 rv:593 (iPhone 4S; iPhone OS 7.0.4; it_IT)\",\n        \"expect\"  : \n        {\n            \"name\"    : \"rad.io\",\n            \"version\" : \"1.18.1\",\n            \"major\"   : \"1\"\n        }\n    },\n    {\n        \"desc\"    : \"BE-Test\",\n        \"ua\"      : \"APP-BE Test/1.0 (iPad; Apple; CPU iPhone OS 7_0_2 like Mac OS X)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BE Test\",\n            \"version\" : \"1.0\",\n            \"major\"   : \"1\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/extension/vehicle.json",
    "content": "[\n    {\n        \"desc\"    : \"BMW\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 9; AFTLBT962E2) AppleWebKit/537.36 (KHTML, like Gecko) Silk/118.3.1 like Chrome/118.0.5993.155 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"vendor\" : \"BMW\",\n            \"model\"  : \"undefined\",\n            \"type\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"BYD\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; DiLink3.0 For BYD AUTO Build/QKQ1.200816.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.186 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"vendor\" : \"BYD\",\n            \"model\"  : \"undefined\",\n            \"type\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Jeep\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 9; AFTLFT962X3) AppleWebKit/537.36 (KHTML, like Gecko) Silk/124.5.2 like Chrome/124.0.6367.248 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"vendor\" : \"Jeep\",\n            \"model\"  : \"Wagooner\",\n            \"type\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Rivian\",\n        \"ua\"      : \"Dalvik/2.1.0 (Linux; U; Android 10; Rivian R1T Build/QQ3A.200605.002)\",\n        \"expect\"  :\n        {\n            \"vendor\" : \"Rivian\",\n            \"model\"  : \"R1T\",\n            \"type\"   : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Tesla\",\n        \"ua\"      : \"Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/2020.36.16-3e9e4e8dd287\",\n        \"expect\"  :\n        {\n            \"vendor\" : \"Tesla\",\n            \"model\"  : \"undefined\",\n            \"type\"   : \"embedded\"\n        }\n    },\n    {\n        \"desc\"    : \"Volvo\",\n        \"ua\"      : \"Mozilla/5.0 (VCC; 1.0; like Gecko) NetFront/4.2\",\n        \"expect\"  :\n        {\n            \"vendor\" : \"Volvo\",\n            \"model\"  : \"undefined\",\n            \"type\"   : \"undefined\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/data/ua/os/aix.json",
    "content": "[\n    {\n        \"desc\"    : \"AIX\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; AIX 000138384C00; en-US; rv:1.0.1) Gecko/20030213 Netscape/7.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AIX\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"AIX\",\n        \"ua\"      : \"Mozilla/5.0 (AIX; SPARC64; smart-thumbtack; Mosaic/2.7) Gecko/20100101 Mosaic/2.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AIX\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"AIX\",\n        \"ua\"      : \"Mozilla/5.0 (X11; N; Linux i686; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Mozilla/3.0 (X11; I; AIX 2) Navigator/9.0.0.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AIX\",\n            \"version\" : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"AIX\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; AIX 7.2; en-US; rv:1.7.12) Gecko/20100101 Firefox/126.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AIX\",\n            \"version\" : \"7.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/amigaos.json",
    "content": "[\n    {\n        \"desc\"    : \"AmigaOS\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; AWEB 3.4 SE; AmigaOS)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"AmigaOS\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/android-x86.json",
    "content": "[\n    {\n        \"desc\"    : \"Android-x86\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 7.1.2; Generic Android-x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 OPR/61.2.3076.56749\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android-x86\",\n            \"version\" : \"7.1.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/android.json",
    "content": "[\n    {\n        \"desc\"    : \"Android\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; VM670 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android\",\n            \"version\" : \"2.2.2\"\n        }\n    },\n    {\n        \"desc\"    : \"MIUI\",\n        \"ua\"      : \"Dalvik/2.1.0 (Linux; U; Android 9; Mi MIX 3 5G MIUI/V10.3.2.0.PEMEUVF)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android\",\n            \"version\" : \"9\"\n        }\n    },\n    {\n        \"desc\"    : \"KTB-Nexus 5\",\n        \"ua\"      : \"APP-My App/1.0 (Linux; Android 4.2.1; Nexus 5 Build/JOP40D)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Android\",\n            \"version\" : \"4.2.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/arcaos.json",
    "content": "[\n    {\n        \"desc\"    : \"ArcaOS\",\n        \"ua\"      : \"Mozilla/5.0 (OS/2; ArcaOS 5.0.6; x86_64; rv:89.0) Gecko/20100101 Firefox/89.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ArcaOS\",\n            \"version\" : \"5.0.6\"\n        }\n    },\n    {\n        \"desc\"    : \"ArcaOS\",\n        \"ua\"      : \"Mozilla/5.0 (OS/2; ArcaOS; x64; rv:89.0) Gecko/20100101 Firefox/89.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"ArcaOS\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/arch.json",
    "content": "[\n    {\n        \"desc\"    : \"Arch\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Arch Linux i686; rv:2.0) Gecko/20100101 Firefox/126.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Arch\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Arch\",\n        \"ua\"      : \"Mozilla/5.0 ArchLinux (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Arch\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Arch\",\n        \"ua\"      : \"Uzbl (Webkit 1.1.10) (Arch Linux)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Arch\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/bada.json",
    "content": "[\n    {\n        \"desc\"    : \"Bada\",\n        \"ua\"      : \"Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S5253/S5253DDKC1; U; Bada/1.0; en-us) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WQVGA SMM-MMS/1.2.0 OPN-B\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Bada\",\n            \"version\" : \"1.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/beos.json",
    "content": "[\n    {\n        \"desc\"    : \"BeOS\",\n        \"ua\"      : \"Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.8pre) Gecko/20070926 SeaMonkey/1.1.5pre\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BeOS\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/blackberry.json",
    "content": "[\n    {\n        \"desc\"    : \"BlackBerry\",\n        \"ua\"      : \"BlackBerry9300/5.0.0.912 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/378\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BlackBerry\",\n            \"version\" : \"5.0.0.912\"\n        }\n    },\n    {\n        \"desc\"    : \"BlackBerry 10\",\n        \"ua\"      : \"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.3+ (KHTML, like Gecko) Version/10.0.9.386 Mobile Safari/537.3+\",\n        \"expect\"  :\n        {\n            \"name\"    : \"BlackBerry\",\n            \"version\" : \"10\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/centos.json",
    "content": "[\n    {\n        \"desc\"    : \"CentOS\",\n        \"ua\"      : \"Konqueror/15.13 (CentOS Linux 7.4; cs-CZ;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"CentOS\",\n            \"version\" : \"7.4\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/chrome-os.json",
    "content": "[\n    {\n        \"desc\"    : \"Chrome OS\",\n        \"ua\"      : \"Mozilla/5.0 (X11; CrOS x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome OS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Chromium OS\",\n        \"ua\"      : \"Mozilla/5.0 (X11; CrOS x86_64 10575.58.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chrome OS\",\n            \"version\" : \"10575.58.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/chromecast-android.json",
    "content": "[\n    {\n        \"desc\"    : \"Google Chromecast with Google TV\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 12.0; Build/STTL.240206.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.0 Safari/537.36 CrKey/1.56.500000 DeviceType/AndroidTV\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chromecast Android\",\n            \"version\" : \"12.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/chromecast-fuchsia.json",
    "content": "[\n    {\n        \"desc\"    : \"Google Chromecast Nest Hub\",\n        \"ua\"      : \"Mozilla/5.0 (Fuchsia) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 CrKey/1.56.500000\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chromecast Fuchsia\",\n            \"version\" : \"1.56.500000\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/chromecast-linux.json",
    "content": "[\n    {\n        \"desc\"    : \"Google Chromecast Legacy Linux-Based\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.81 Safari/537.36 CrKey/1.42.183786\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chromecast Linux\",\n            \"version\" : \"1.42.183786\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/chromecast-smartspeaker.json",
    "content": "[\n    {\n        \"desc\"    : \"Google Chromecast Mini Smart Speaker\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.225 Safari/537.36 CrKey/1.56.500000 DeviceType/SmartSpeaker\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Chromecast SmartSpeaker\",\n            \"version\" : \"1.56.500000\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/contiki.json",
    "content": "[\n    {\n        \"desc\"    : \"Contiki\",\n        \"ua\"      : \"Contiki/1.0 (Commodore 64; http://dunkels.com/adam/contiki/)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Contiki\",\n            \"version\" : \"1.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/debian.json",
    "content": "[\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.7 (like Gecko) (Debian)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Debian\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; Debian GNU/Linux 8.1 (jessie)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.0 Maxthon/1.0.5.3 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Debian\",\n            \"version\" : \"8.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"ELinks/0.12~pre5-4 (textmode; Debian; Linux 3.2.0-4-amd64 x86_64 192x47-2)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Debian\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"w3m/0.5.3+debian-19\",\n        \"expect\"  :\n        {\n            \"name\"    : \"debian\",\n            \"version\" : \"19\"\n        }\n    },\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Debian\",\n            \"version\" : \"3.0.1-1\"\n        }\n    },\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.24.4; X11) KHTML/3.5.9 (like Gecko) (Debian package 4:3.5.9.dfsg.1-2+b1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Debian\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Debian\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux sparc64; es-PY; rv:5.0) Gecko/20100101 IceCat/5.0 (like Firefox/5.0; Debian-6.0.1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Debian\",\n            \"version\" : \"6.0.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/deepin.json",
    "content": "[\n    {\n        \"desc\"    : \"Deepin\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64; Deepin 15.5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36 NFSBrowser/5.0.0.1886\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Deepin\",\n            \"version\" : \"15.5\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/dragonfly.json",
    "content": "[\n    {\n        \"desc\"    : \"DragonFly\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; DragonFly i386; de; rv:1.9.1) Gecko/20090720 Firefox/3.5.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"DragonFly\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/elementary-os.json",
    "content": "[\n    {\n        \"desc\"    : \"elementary OS\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/604.1 (KHTML, like Gecko) Version/11.0 Safari/604.1 elementary OS/0.4 (Loki) Epiphany/3.18.11\",\n        \"expect\"  :\n        {\n            \"name\"    : \"elementary OS\",\n            \"version\" : \"0.4\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/fedora.json",
    "content": "[\n    {\n        \"desc\"    : \"Fedora\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fedora\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Fedora\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:2.0) Gecko/20110404 Fedora/16-dev Firefox/4.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fedora\",\n            \"version\" : \"16-dev\"\n        }\n    },\n    {\n        \"desc\"    : \"Fedora\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; sk; rv:1.9.0.4) Gecko/2008111217 Fedora/3.0.4-1.fc10 Firefox/3.0.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fedora\",\n            \"version\" : \"3.0.4-1.fc10\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/firefox-os.json",
    "content": "[\n    {\n        \"desc\"    : \"Firefox OS\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"14.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on Tablet\",\n        \"ua\"      : \"Mozilla/5.0 (Tablet; rv:26.0) Gecko/26.0 Firefox/26.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"26.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on TV\",\n        \"ua\"      : \"Mozilla/5.0 (TV; rv:44.0) Gecko/44.0 Firefox/44.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"44.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on Alcatel One Touch Fire\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; ALCATELOneTouch4012X; rv:18.1) Gecko/18.1 Firefox/18.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"18.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on Huawei Y300II\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; HUAWEIY300-F1; rv:18.1) Gecko/18.1 Firefox/18.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"18.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on LG Fireweb\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; LG-D300; rv:18.1) Gecko/18.1 Firefox/18.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"18.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on LG FX0\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; LGL25; rv:32.0) Gecko/32.0 Firefox/32.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"32.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on Panasonic Viera TV\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Viera; rv:34.0) Gecko/20100101 Firefox/34.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"34.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Firefox OS on ZTE Open\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; ZTEOPEN; rv:18.1) Gecko/18.1 Firefox/18.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Firefox OS\",\n            \"version\" : \"18.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/freebsd.json",
    "content": "[\n    {\n        \"desc\"    : \"FreeBSD\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16\",\n        \"expect\"  :\n        {\n            \"name\"    : \"FreeBSD\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"FreeBSD\",\n        \"ua\"      : \"Mozilla/5.0 (X11; FreeBSD; U; Viera; pl-PL) AppleWebKit/537.11 (KHTML, like Gecko) Viera/3.3.3 Chrome/23.0.1271.97 Safari/537.11\",\n        \"expect\"  :\n        {\n            \"name\"    : \"FreeBSD\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/fuchsia.json",
    "content": "[\n    {\n        \"desc\"    : \"Fuchsia\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Fuchsia x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3557.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fuchsia\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Fuchsia\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Mozilla/5.0 (X11; Linux; Fuchsia; GoogleTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Large Screen Safari/537.36 GoogleTV\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Fuchsia\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/gentoo.json",
    "content": "[\n\n    {\n        \"desc\"    : \"Gentoo\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.16) Gecko/20080716 (Gentoo) Galeon/2.0.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Gentoo\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Gentoo\",\n        \"ua\"      : \"Xombrero (X11; U; Gentoo Linux amd64; en-US) Webkit/2.8.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Gentoo\",\n            \"version\" : \"amd64\"\n        }\n    },\n    {\n        \"desc\"    : \"Gentoo\",\n        \"ua\"      : \"Xombrero/1.6.4 (Linux amd64; en; Gentoo)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Gentoo\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Gentoo\",\n        \"ua\"      : \"Links (2.8; Linux 3.17.2-gentoo-x86 i686; GNU C 4.8.2; x)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"gentoo\",\n            \"version\" : \"x86\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/ghostbsd.json",
    "content": "[\n    {\n        \"desc\"    : \"GhostBSD\",\n        \"ua\"      : \"Mozilla/5.0 (X11; GhostBSD/10.3; x86_64; rv:50.0.1) Gecko/20100101 Firefox/50.0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"GhostBSD\",\n            \"version\" : \"10.3\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/haiku.json",
    "content": "[\n    {\n        \"desc\"    : \"Haiku\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Haiku R1 x86) AppleWebKit/602.1.1 (KHTML, like Gecko) WebPositive/1.2 Version/8.0 Safari/602.1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Haiku\",\n            \"version\" : \"R1\"\n        }\n    },\n    {\n        \"desc\"    : \"Haiku\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Haiku x86_64; rv:128.0) Gecko/20100101 Firefox/128.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Haiku\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Haiku\",\n        \"ua\"      : \"Mozilla/5.0 (Haiku; BeOS; rv:99.0) Gecko/20100101 Firefox/99.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Haiku\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Haiku\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Haiku BePC) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.17 Chrome/87.0.4280.144 Safari/537.36 Dooble/2023.12.25 Dooble/2023.12.25\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Haiku\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/harmonyos.json",
    "content": "[\n    {\n        \"desc\"    : \"HarmonyOS\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; HarmonyOS; YAL-AL10; HMSCore 6.3.0.327; GMSCore 21.48.15) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.105 HuaweiBrowser/12.0.3.310 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HarmonyOS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"HarmonyOS 2\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 10; STK-AL00 Build/HUAWEISTK-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/88.0.4324.93 Mobile Safari/537.36 BDOS/1.0 (HarmonyOS 2.2.0) SP-engine/2.72.0 baiduboxapp/13.34.5.10 (Baidu; P1 10) NABar/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HarmonyOS\",\n            \"version\" : \"2.2.0\"\n        }\n    },\n    {\n        \"desc\"    : \"HarmonyOS 3\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 12; Huawei P60 Pro Build/HarmonyOS 3.1.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.1.6136.139 Mobile Safari/537.36 OPR/111.11\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HarmonyOS\",\n            \"version\" : \"3.1.0\"\n        }\n    },\n    {\n        \"desc\"    : \"HarmonyOS 4\",\n        \"ua\"      : \"Mozilla/5.0 (Android 12; HarmonyOS 4.0.0.118; OXF-AN00 Build/HUAWEIOXF-AN00; HMSCore 6.13.0.302; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36 EdgA/125.0.0.0 Language/zh_TW ABI/arm64-v8a\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HarmonyOS\",\n            \"version\" : \"4.0.0.118\"\n        }\n    },\n    {\n        \"desc\"    : \"HarmonyOS 4\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Android 12; HarmonyOS/4.0.3.601; JAD-AL50; HMSCore/6.13.0.320 Build/AP31.240223.016.A3; x64; ARM64) AppleWebKit/537.36 (KHTML, like Gecko) HuaweiBrowser/14.0.7.302 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HarmonyOS\",\n            \"version\" : \"4.0.3.601\"\n        }\n    },\n    {\n        \"desc\"    : \"HarmonyOS 5\",\n        \"ua\"      : \"Mozilla/5.0 (PC; OpenHarmony 5.0; HarmonyOS 5.0) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Browser/harmony360Browser/1.0.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HarmonyOS\",\n            \"version\" : \"5.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/hp-ux.json",
    "content": "[\n    {\n        \"desc\"    : \"HP-UX\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; HP-UX 9000/785; es-ES; rv:1.0.1) Gecko/20020827 Netscape/7.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"HP-UX\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/hurd.json",
    "content": "[\n    {\n        \"desc\"    : \"Hurd\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Hurd 0.9 i386; en-US) libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/3.7.0 Safari/696.96\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Hurd\",\n            \"version\" : \"0.9\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/ios.json",
    "content": "[\n    {\n        \"desc\"    : \"iOS 18.6\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Mobile/15E148 Safari/604.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"18.6\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS 26\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"26.0\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS 26\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Mobile/15E148 Safari/604.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"26.2\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS in App\",\n        \"ua\"      : \"AppName/version CFNetwork/version Darwin/version\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS with Chrome\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"5.1.1\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS with DuckDuckGo\",\n        \"ua\"      : \"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1 Ddg/26.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"26.0\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS with Opera Mini\",\n        \"ua\"      : \"Opera/9.80 (iPhone; Opera Mini/7.1.32694/27.1407; U; en) Presto/2.8.119 Version/11.10\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\": \"iOS with FaceBook Mobile App\",\n        \"ua\": \"[FBAN/FBIOS;FBAV/283.0.0.44.117;FBBV/238386386;FBDV/iPhone12,1;FBMD/iPhone;FBSN/iOS;FBSV/13.6.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBRV/240127608]\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"13.6.1\"\n        }\n    },\n    {\n        \"desc\": \"iOS with Instagram\",\n        \"ua\": \"Instagram 5.0.2 (iPhone5,1; iPhone OS 7_0_4; en_US; en) AppleWebKit/420+\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"7.0.4\"\n        }\n    },\n    {\n        \"desc\": \"iOS with MS Word App\",\n        \"ua\": \"Microsoft Office Word/2.44.1211 (iOS/13.7; Tablet; es-MX; AppStore; Apple/iPad11,3)\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"13.7\"\n        }\n    },\n    {\n        \"desc\": \"iOS with Quora App\",\n        \"ua\": \"Quora 8.4.30 rv:3230 env:prod (iPad11,3; iPadOS 17.7; en_GB) AppleWebKit\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"17.7\"\n        }\n    },\n    {\n        \"desc\": \"iOS with Slack App\",\n        \"ua\": \"com.tinyspeck.chatlyio/23.04.10 (iPhone; iOS 16.4.1; Scale/3.00)\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"16.4.1\"\n        }\n    },\n    {\n        \"desc\": \"iOS with Snapchat\",\n        \"ua\": \"Snapchat/12.12.1.40 (iPhone15,2; iOS 16.2; gzip)\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"16.2\"\n        }\n    },\n    {\n        \"desc\": \"iOS with Spotify App\",\n        \"ua\": \"Spotify/8.7.70 iOS/16.0 (iPhone15,3)\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"16.0\"\n        }\n    },\n    {\n        \"desc\": \"iOS with TuneIn Radio App\",\n        \"ua\": \"TuneIn Radio/27.1.0; iPad6,3; iPadOS/16.6\",\n        \"expect\":\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"16.6\"\n        }\n    },\n    {\n        \"desc\"    : \"iOS BE App\",\n        \"ua\"      : \"APP-BE Test/1.0 (iPad; Apple; CPU iPhone OS 7_0_2 like Mac OS X)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"7.0.2\"\n        }\n    },\n    {\n        \"desc\": \"Apple HomePod\",\n        \"ua\": \"AppleCoreMedia/1.0.0.15D61 (HomePod; U; CPU OS 11_2_5 like Mac OS X; en_us)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"11.2.5\"\n        }\n    },\n    {\n        \"desc\": \"iOS\",\n        \"ua\": \"iPlayTV/3.3.9 (Apple TV; iOS 16.1; Scale/1.00)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"16.1\"\n        }\n    },\n    {\n        \"desc\": \"iOS\",\n        \"ua\": \"itunesstored/1.0 iOS/8.4.4 AppleTV/7.8 model/AppleTV3,2 build/12H937 (3; dt:12)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"8.4.4\"\n        }\n    },\n    {\n        \"desc\": \"tvOS\",\n        \"ua\": \"iMPlayer/1.6.1 (tvOS 26.0.1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"26.0.1\"\n        }\n    },\n    {\n        \"desc\": \"tvOS\",\n        \"ua\": \"otg/1.5.1 (AppleTv Apple TV 4; tvOS16.2; appletv.client) libcurl/7.58.0 OpenSSL/1.0.2o zlib/1.2.11 clib/1.8.56\",\n        \"expect\"  :\n        {\n            \"name\"    : \"iOS\",\n            \"version\" : \"16.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/joli.json",
    "content": "[\n    {\n        \"desc\"    : \"Joli\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Jolicloud Linux i686) AppleWebKit/537.6 (KHTML, like Gecko) Joli OS/1.2 Chromium/23.0.1240.0 Chrome/23.0.1240.0 Safari/537.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Joli\",\n            \"version\" : \"1.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/kaios.json",
    "content": "[\n    {\n        \"desc\"    : \"KaiOS\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; Nokia_8110_4G; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"KAIOS\",\n            \"version\" : \"2.5\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/knoppix.json",
    "content": "[\n    {\n        \"desc\"    : \"Knoppix\",\n        \"ua\"      : \"Mozilla/5.0 (Knoppix; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Knoppix\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/kubuntu.json",
    "content": "[\n    {\n        \"desc\"    : \"Kubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Kubuntu\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Kubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (Kubuntu; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Kubuntu\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/linpus.json",
    "content": "[\n    {\n        \"desc\"    : \"Linpus\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9b5pre) Gecko/2008032619 Linpus/3.0-0.49\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Linpus\",\n            \"version\" : \"3.0-0.49\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/linspire.json",
    "content": "[\n    {\n        \"desc\"    : \"Linspire\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4) Gecko/20060803 Firefox/1.5.0.4 Linspire/1.5.0.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Linspire\",\n            \"version\" : \"1.5.0.4\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/linux.json",
    "content": "[\n    {\n        \"desc\"    : \"Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Linux\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Linux\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Linux\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/macos.json",
    "content": "[\n    {\n        \"desc\"    : \"Mac OS on PowerPC\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"macOS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac OS X on x86, x86_64, or aarch64 using Firefox\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"macOS\",\n            \"version\" : \"x.y\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac OS X on PowerPC using Firefox\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; PPC Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"macOS\",\n            \"version\" : \"x.y\"\n        }\n    },\n    {\n        \"desc\"    : \"Mac OS\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"macOS\",\n            \"version\" : \"10.6.8\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/maemo.json",
    "content": "[\n    {\n        \"desc\"    : \"Nokia N900 Linux mobile, on the Fennec browser\",\n        \"ua\"      : \"Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0) Gecko/20100101 Firefox/10.0 Fennec/10.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maemo\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia N900 Linux mobile, on the Maemo browser\",\n        \"ua\"      : \"Mozilla/5.0(X11; U; Linux armv7l; fr-FR; rv:1.9.2a1pre) Gecko/20091127 Firefox/3.5 Maemo Browser 1.5.6 RX-51 N900\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maemo\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia N900 Linux mobile, on the Maemo browser\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Maemo 5.0; Nokia N900; Build/4.0.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Maemo\",\n            \"version\" : \"5.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/mandriva.json",
    "content": "[\n    {\n        \"desc\"    : \"Mandriva\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.22) Gecko/20110907 Mandriva Linux/1.9.2.22-0.1mdv2010.2 (2010.2) Firefox/3.6.22\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mandriva\",\n            \"version\" : \"1.9.2.22-0.1mdv2010.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/manjaro.json",
    "content": "[\n    {\n        \"desc\"    : \"Manjaro\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Manjaro 19.0.2; Arch; x64; rv:84.0) Gecko/20100101 Firefox/84.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Manjaro\",\n            \"version\" : \"19.0.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/meego.json",
    "content": "[\n    {\n        \"desc\"    : \"MeeGo\",\n        \"ua\"      : \"Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MeeGo\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/minix.json",
    "content": "[\n    {\n        \"desc\"    : \"Minix\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Original ; Minix 3.3 ; rv:3.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Minix\",\n            \"version\" : \"3.3\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/mint.json",
    "content": "[\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Opera/9.80 (X11; Linux x86_64; Edition Linux Mint) Presto/2.12.388 Version/12.16\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Opera/9.64 (X11; Linux i686; U; Linux Mint; nb) Presto/2.1.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Linux Mint/6 (Felicia) Firefox/3.0.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Linux Mint/6 (Felicia) Firefox/3.0.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"6\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Opera/9.80 (X11; Linux i686; Edition Linux Mint) Presto/2.12.388 Version/12.15\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Opera/9.51 (X11; Linux i686; U; Linux Mint; en)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux Mint/19.3 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/83.0.4103.97 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"19.3\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux Mint/20 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Kiwi Chrome/100.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"20\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux Mint/20.2; x86_64) Gecko/20100101 Firefox/92.0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"20.2\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.10) Gecko/2009042513 Linux Mint/5 (Elyssa) Firefox/3.0.10\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060308 Linux Mint/7 (Gloria) Firefox/54.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Linux Mint/8 (Helena) Firefox/3.5.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:2.0) Gecko/20100101 Linux Mint 16/Petra Firefox/25.0.1.\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"16\"\n        }\n    },\n    {\n        \"desc\"    : \"Mint\",\n        \"ua\"      : \"Mozilla/5.0 (Linux x86_64; Mint 21.3) AppleWebKit/537.36 (KHTML, like Gecko) Brave/128.0.0.0 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Mint\",\n            \"version\" : \"21.3\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/morphos.json",
    "content": "[\n    {\n        \"desc\"    : \"MorphOS\",\n        \"ua\"      : \"AmigaVoyager/3.4.4 (MorphOS/PPC native)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MorphOS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"MorphOS\",\n        \"ua\"      : \"Mozilla/5.0 (Macintosh; PowerPC MorphOS 3.7; Odyssey Web Browser; rv:1.23) AppleWebKit/538.1 (KHTML, like Gecko) OWB/1.23 Safari/538.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MorphOS\",\n            \"version\" : \"3.7\"\n        }\n    },\n    {\n        \"desc\"    : \"MorphOS\",\n        \"ua\"      : \"Mozilla/5.0 (X11; MorphOS ppc64; rv:88.0) Gecko/20100101 Firefox/88.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MorphOS\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"MorphOS\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Origyn Web Browser; MorphOS; PPC; U) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"MorphOS\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/netbsd.json",
    "content": "[\n    {\n        \"desc\"    : \"NetBSD\",\n        \"ua\"      : \"ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NetBSD\",\n            \"version\" : \"3.0.2PATCH\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/netrange.json",
    "content": "[\n    {\n        \"desc\"    : \"Netrange Smart TV\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36 OPR/46.0.2207.0 LOEWE-SL410/5.2.0.0 HbbTV/1.4.1 (; LOEWE; SL410; LOH/5.2.0.0;;) FVC/3.0 (LOEWE; SL410;) CE-HTML/1.0 Config (L:deu,CC:DEU) NETRANGEMMH\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NETRANGE\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/nettv.json",
    "content": "[\n    {\n        \"desc\"    : \"NetTV 3.2.1\",\n        \"ua\"      : \"Opera/9.80 (Linux mips ; U; HbbTV/1.1.1 (; Philips; ; ; ; ) CE-HTML/1.0 NETTV/3.2.1; en) Presto/2.6.33 Version/10.70\",\n        \"expect\"  :\n        {\n            \"name\"    : \"NETTV\",\n            \"version\" : \"3.2.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/nintendo.json",
    "content": "[\n    {\n        \"desc\"    : \"Nintendo Switch\",\n        \"ua\"      : \"Mozilla/5.0 (Nintendo Switch; WifiWebAuthApplet) AppleWebKit/606.4 (KHTML, like Gecko) NF/6.0.1.15.4 NintendoBrowser/5.1.0.20393\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Nintendo\",\n            \"version\" : \"Switch\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/openbsd.json",
    "content": "[\n    {\n        \"desc\"    : \"OpenBSD\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.1) Gecko/20090702 Firefox/3.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OpenBSD\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/openharmony.json",
    "content": "[\n    {\n        \"desc\"    : \"OpenHarmony\",\n        \"ua\"      : \"Mozilla/5.0 (Phone; OpenHarmony 4.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OpenHarmony\",\n            \"version\" : \"4.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/os2.json",
    "content": "[\n    {\n        \"desc\"    : \"OS/2\",\n        \"ua\"      : \"Links (2.1pre14; OS/2 1 i386; 80x33)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OS/2\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"OS/2\",\n        \"ua\"      : \"Mozilla/5.0 (OS/2; OS/2 i386) AppleWebKit/538.36 (KHTML, like Gecko) QtWebEngine/5.15.2 Chrome/127.0.6533.72\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OS/2\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"OS/2\",\n        \"ua\"      : \"Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"OS/2\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/palm.json",
    "content": "[\n    {\n        \"desc\"    : \"Palm OS\",\n        \"ua\"      : \"Mozilla/4.76 [en] (PalmOS; U; WebPro3.0; Palm-Arz1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Palm\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/pclinuxos.json",
    "content": "[\n    {\n        \"desc\"    : \"PCLinuxOS\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101209 PCLinuxOS/1.9.2.13-1pclos2010 (2010) Firefox/3.6.13\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PCLinuxOS\",\n            \"version\" : \"1.9.2.13-1pclos2010\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/pico.json",
    "content": "[\n    {\n        \"desc\": \"Pico 4\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.8.2 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.38 Chrome/105.0.5195.68 VR Safari/537.36\",\n        \"expect\": {\n            \"name\"    : \"PICO\",\n            \"version\" : \"5.8.2\"\n        }\n    },\n    {\n        \"desc\": \"Pico 4\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; PICO 4 OS5.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36 OculusBrowser/7.0\",\n        \"expect\": {\n            \"name\"    : \"PICO\",\n            \"version\" : \"5.4.0\"\n        }\n    },\n    {\n        \"desc\": \"Pico Neo3 Link\",\n        \"ua\": \"Mozilla/5.0 (X11; Linux x86_64; Pico Neo3 Link OS5.8.4.0 like Quest) AppleWebKit/537.36 (KHTML, like Gecko) PicoBrowser/3.3.22 Chrome/105.0.5195.68 VR Safari/537.36\",\n        \"expect\": {\n            \"name\"    : \"Pico\",\n            \"version\" : \"5.8.4.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/plan9.json",
    "content": "[\n    {\n        \"desc\"    : \"Plan9\",\n        \"ua\"      : \"NCSA_Mosaic/5.0 (X11;Plan 9 4.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Plan 9\",\n            \"version\" : \"4.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/playstation.json",
    "content": "[\n    {\n        \"desc\"    : \"PlayStation 4\",\n        \"ua\"      : \"Mozilla/5.0 (PlayStation 4 3.00) AppleWebKit/537.73 (KHTML, like Gecko)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PlayStation\",\n            \"version\" : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"PlayStation 5\",\n        \"ua\"      : \"Mozilla/5.0 (PlayStation 5/SmartTV) AppleWebKit/605.1.15 (KHTML, like Gecko)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"PlayStation\",\n            \"version\" : \"5\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/qnx.json",
    "content": "[\n    {\n        \"desc\"    : \"QNX\",\n        \"ua\"      : \"Mozilla/5.0 (Photon; U; QNX x86pc; en-US; rv:1.8.1.20) Gecko/20090127 BonEcho/2.0.0.20\",\n        \"expect\"  :\n        {\n            \"name\"    : \"QNX\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/raspbian.json",
    "content": "[\n    {\n        \"desc\"    : \"Raspbian\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/72.0.3626.121 HeadlessChrome/72.0.3626.121 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Raspbian\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Raspbian\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/538.15 (KHTML, like Gecko) Version/8.0 Safari/538.15 Raspbian/9.0 (1:3.8.2.0-0rpi28) Epiphany/3.8.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Raspbian\",\n            \"version\" : \"9.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/redhat.json",
    "content": "[\n    {\n        \"desc\"    : \"RedHat\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.4 (like Gecko) Red Hat Enterprise Linux/4.3.4-11.el6_1.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Red Hat\",\n            \"version\" : \"4.3.4-11.el6_1.4\"\n        }\n    },\n    {\n        \"desc\"    : \"RedHat\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.13pre) Gecko/20070717 Red Hat/1.0.9-4.el4 SeaMonkey/1.0.9\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Red Hat\",\n            \"version\" : \"1.0.9-4.el4\"\n        }\n    },\n    {\n        \"desc\"    : \"RedHat\",\n        \"ua\"      : \"iTunes/4.7.1 (Linux; N; Red Hat; x86_64-linux; EN; utf8) SqueezeCenter, Squeezebox Server, Logitech Media Server/7.9.1/1522157629\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Red Hat\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"RedHat\",\n        \"ua\"      : \"curl/7.20.0 (x86_64-redhat-linux-gnu) libcurl/7.20.0 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"redhat\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/rim-tablet-os.json",
    "content": "[\n    {\n        \"desc\"    : \"RIM Tablet OS\",\n        \"ua\"      : \"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+\",\n        \"expect\"  :\n        {\n            \"name\"    : \"RIM Tablet OS\",\n            \"version\" : \"2.1.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/risc-os.json",
    "content": "[\n    {\n        \"desc\"    : \"RISC OS\",\n        \"ua\"      : \"Mozilla/1.10 [en] (Compatible; RISC OS 3.70; Oregano 1.10)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"RISC OS\",\n            \"version\" : \"3.70\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/sabayon.json",
    "content": "[\n    {\n        \"desc\"    : \"Sabayon\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Sabayon Chrome/19.0.1084.46 Safari/536.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sabayon\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/sailfish.json",
    "content": "[\n    {\n        \"desc\"    : \"Sailfish\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; U; Sailfish 3.0; Mobile; rv:45.0) Gecko/45.0 Firefox/45.0 SailfishBrowser/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Sailfish\",\n            \"version\" : \"3.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/serenityos.json",
    "content": "[\n    {\n        \"desc\"    : \"SerenityOS\",\n        \"ua\"      : \"Mozilla/4.0 (SerenityOS; x86) LibWeb+LibJS (Not KHTML, nor Gecko) LibWeb\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SerenityOS\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/series40.json",
    "content": "[\n    {\n        \"desc\"    : \"Series40\",\n        \"ua\"      : \"Mozilla/5.0 (Series40; Nokia2055/03.20; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.2.0.0.34\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Series40\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/slackware.json",
    "content": "[\n    {\n        \"desc\"    : \"Slackware\",\n        \"ua\"      : \"Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Slackware\",\n            \"version\" : \"13.37\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/solaris.json",
    "content": "[\n    {\n        \"desc\"    : \"Solaris\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20070606\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Solaris\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Solaris\",\n        \"ua\"      : \"Mozilla/5.0 (Solaris; SPARC; w3m/0.5.3; rv:1.0) Gecko/20100101 w3m/0.5.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Solaris\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Solaris\",\n        \"ua\"      : \"NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Solaris\",\n            \"version\" : \"4.1.4\"\n        }\n    },\n    {\n        \"desc\"    : \"Solaris\",\n        \"ua\"      : \"Opera/5.0 (SunOS 5.8 sun4m; U) [en]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Solaris\",\n            \"version\" : \"5.8\"\n        }\n    },\n    {\n        \"desc\"    : \"Solaris\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100215 Solaris/10.1 (GNU) Superswan/3.5.8 (Byte/me)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Solaris\",\n            \"version\" : \"10.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/suse.json",
    "content": "[\n    {\n        \"desc\"    : \"OpenSUSE\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110420 SUSE/3.6.17-0.2.1 Firefox/3.6.17\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SUSE\",\n            \"version\" : \"3.6.17-0.2.1\"\n        }\n    },\n    {\n        \"desc\"    : \"SUSE\",\n        \"ua\"      : \"Mozilla/5.0 (X11; SUSE; Linux amd64; rv:86.0) Gecko/20100101 Firefox/86.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"SUSE\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/symbian.json",
    "content": "[\n    {\n        \"desc\"    : \"Nokia 5250\",\n        \"ua\"      : \"Nokia5250/10.0.011 (SymbianOS/9.4; U; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Safari/525 3gpp-gba\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"9.4\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia N79\",\n        \"ua\"      : \"Mozilla/5.0 (SymbianOS/9.3; U; Series60/3.2 NokiaN79-1/32.001; Profile/MIDP-2.1 Configuration/CLDC-1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"9.3\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia E71\",\n        \"ua\"      : \"Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE71-1/110.07.127; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"9.2\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera Mini on S60\",\n        \"ua\"      : \"Opera/9.80 (Series 60; Opera Mini/7.1.32444/191.361; U; de) Presto/2.12.423 Version/12.16\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"NokiaBrowser on Nokia C7\",\n        \"ua\"      : \"Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC7-00/024.001; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.37 Mobile Safari/533.4 3gpp-gba\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia 808 PureView\",\n        \"ua\"      : \"Mozilla/5.0 (Symbian/3; Series60/5.5 Nokia808PureView/113.010.1508; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/535.1 (KHTML, like Gecko) NokiaBrowser/8.3.2.21 Mobile Safari/535.1 3gpp-gba\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"Nokia 808 PureView\",\n        \"ua\"      : \"Mozilla/5.0 (Symbian; U; Nokia808 PureView; en-GB) AppleWebKit/534.3 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Mobile Safari/534.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Symbian\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/tizen.json",
    "content": "[\n    {\n        \"desc\"    : \"Tizen\",\n        \"ua\"      : \"Mozilla/5.0 (SMART-TV; Linux; Tizen 2.3) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.0 TV Safari/538.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tizen\",\n            \"version\" : \"2.3\"\n        }\n    },\n    {\n        \"desc\"    : \"Tizen\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Tizen 2.3; SAMSUNG SM-Z130H) AppleWebKit/537.3 (KHTML, like Gecko) Version/2.3 Mobile Safari/537.3\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tizen\",\n            \"version\" : \"2.3\"\n        }\n    },\n    {\n        \"desc\"    : \"Tizen 6.0\",\n        \"ua\"      : \"HbbTV/1.5.1 (+DRM;Samsung;SmartTV2021:UAU7000;T-KSU2EDEUC-1506.0;KantSU2e;urn:samsungtv:familyname:21_KANTSU2E_UHD_BASIC:2021;) Tizen/6.0 (+TVPLUS+SmartHubLink) Chrome/76 LaTivu_1.0.1_2021 RVID/17\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Tizen\",\n            \"version\" : \"6.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/ubuntu-touch.json",
    "content": "[\n    {\n        \"desc\"    : \"Ubuntu Touch\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Ubuntu 16.04 like Android 4.4) AppleWebKit/537.36 Chromium/65.0.3325.151 Mobile Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ubuntu Touch\",\n            \"version\" : \"16.04\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/ubuntu.json",
    "content": "[\n    {\n        \"desc\"    : \"Ubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.22+ (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/535.22+ Ubuntu/12.04 (3.4.1-0ubuntu1) Epiphany/3.4.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ubuntu\",\n            \"version\" : \"12.04\"\n        }\n    },\n    {\n        \"desc\"    : \"Ubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/31.0.1650.63 Chrome/31.0.1650.63 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ubuntu\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Ubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (Wayland; Linux x86_64; Huawei) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Ubuntu/23.04 Edg/110.0.1587.41\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ubuntu\",\n            \"version\" : \"23.04\"\n        }\n    },\n    {\n        \"desc\"    : \"Ubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Ubuntu 20.04; Linux arm; rv:99.0) Gecko/20100101 Firefox/99.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ubuntu\",\n            \"version\" : \"20.04\"\n        }\n    },\n    {\n        \"desc\"    : \"Ubuntu\",\n        \"ua\"      : \"Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Ubuntu\",\n            \"version\" : \"14.10\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/unix.json",
    "content": "[\n    {\n        \"desc\"    : \"UNIX\",\n        \"ua\"      : \"Surf/0.4.1 (X11; U; Unix; en-US) AppleWebKit/531.2+ Compatible (Safari)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Unix\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/vegaos.json",
    "content": "[\n    {\n        \"desc\"    : \"Vega OS\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Kepler 1.1; AFTCA002 user/1234; wv) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Chrome/130.0.6723.192 Safari/537.36'\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Vega OS\",\n            \"version\" : \"1.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Vega OS\",\n        \"ua\"      : \"Mozilla/5.0 (Linux; Kepler 1.1; AEOHP userdebug/TOT; wv) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Chrome/128.0.6613.194 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Vega OS\",\n            \"version\" : \"1.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/watchos.json",
    "content": "[\n    {\n        \"desc\"    : \"watchOS\",\n        \"ua\"      : \"server-bag [Watch OS,8.4,19S546,Watch3,4]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"watchOS\",\n            \"version\" : \"8.4\"\n        }\n    },\n    {\n        \"desc\"    : \"watchOS\",\n        \"ua\"      : \"atc/1.0 watchOS/7.4.1 model/Watch3,3 hwp/t8004 build/18T201 (6; dt:155)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"watchOS\",\n            \"version\" : \"7.4.1\"\n        }\n    },\n    {\n        \"desc\"    : \"watchOS\",\n        \"ua\"      : \"Watch4,3/5.3.8 (16U680)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"watchOS\",\n            \"version\" : \"5.3.8\"\n        }\n    },\n    {\n        \"desc\"    : \"watchOS\",\n        \"ua\"      : \"BBCNewsUKWatchApp/4.3.0 (Watch2,4; watchOS 3.2.2)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"watchOS\",\n            \"version\" : \"3.2.2\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/webos.json",
    "content": "[\n    {\n        \"desc\"    : \"HP WebOS\",\n        \"ua\"      : \"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.5; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.83 Safari/534.6 TouchPad/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"3.0.5\"\n        }\n    },\n    {\n        \"desc\"    : \"Palm WebOS\",\n        \"ua\"      : \"Mozilla/5.0 (webOS/1.4.5; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"1.4.5\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 22\",\n        \"ua\"      : \" Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/87.0.4280.88 Safari/537.36 LG Browser/8.00.00(LGE; ST50K-LG2200WEB; 04.42.26; 0x00000001; DTV_C22P); webOS.TV-2022; LG NetCast.TV-2013 Compatible (LGE, ST50K-LG2200WEB, wireless)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"22\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 22\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 HbbTV/1.6.1 (+DRM; LGE/SILICONPLAYER/Hyundai; 50HYN3205; WEBOS22 04.42.26; W22_K8LP; DTV_C22P;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"22\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 5.0\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/68.0.3440.106 Safari/537.36 LG Browser/8.00.00(LGE; SWU-6522; 04.50.63; 0x00000001; DTV_C20P); webOS.TV-2020; LG NetCast.TV-2013 Compatible (LGE, SWU-6522, wireless)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 5.0\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 HbbTV/1.5.1 (+DRM; LGE/WALTON/Hyundai; 50HYN3205; WEBOS5.0 04.50.63; W50_K6LP; DTV_C20P;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"5.0\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 5.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 WebAppManager\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 5.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chr0me/68.0.3440.106 Safari/537.36 LG Browser/8.00.00(LGE; E65A71B-S; 04.50.63; 0x00000001; DTV_C20P); webOS.TV-2020; LG NetCast.TV-2013 Compatible (LGE, E65A71B-S, wired)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"5\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 4.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.34 Safari/537.36 WebAppManager\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"4\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 3.5\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 HbbTV/1.3.1 ( DRM; LGE; OLED55B7V-T; WEBOS3.5 06.10.60; W3_M16P; ) FVC/2.0 (LGE; WEBOS3.5 ;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"3.5\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 3.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.2.1 Chrome/38.0.2125.122 Safari/537.36 WebAppManager\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"3\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 2.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/538.2 (KHTML, like Gecko) Large Screen WebAppManager Safari/538.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"2\"\n        }\n    },\n    {\n        \"desc\"    : \"WebOS TV 1.x\",\n        \"ua\"      : \"Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41\",\n        \"expect\"  :\n        {\n            \"name\"    : \"webOS\",\n            \"version\" : \"1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/windows-ce.json",
    "content": "[\n    {\n        \"desc\"    : \"Windows CE\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows CE\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows CE\",\n        \"ua\"      : \"Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows CE\",\n            \"version\" : \"1.0.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/windows-iot.json",
    "content": "[\n    {\n        \"desc\"    : \"Windows IoT\",\n        \"ua\"      : \"Mozilla/5.0 (Windows IoT 10.0; Android 6.0.1; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Mobile Safari/537.36 Edge/18.17763\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows IoT\",\n            \"version\" : \"10.0\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/windows-mobile.json",
    "content": "[\n    {\n        \"desc\"    : \"Windows Mobile\",\n        \"ua\"      : \"Mozilla/5.0 (ZTE-E_N72/N72V1.0.0B02;U;Windows Mobile/6.1;Profile/MIDP-2.0 Configuration/CLDC-1.1;320*240;CTC/2.0) IE/6.0 (compatible; MSIE 4.01; Windows CE; PPC)/UC Browser7.7.1.88\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Mobile\",\n            \"version\" : \"6.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Mobile\",\n        \"ua\"      : \"Opera/9.80 (Windows Mobile; WCE; Opera Mobi/WMD-50433; U; en) Presto/2.4.13 Version/10.00\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Mobile\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Mobile\",\n        \"ua\"      : \"Opera/9.7 (Windows Mobile; PPC; Opera Mobi/35166; U; en) Presto/2.2.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Mobile\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Mobile 6.1\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) 320x240; VZW; Motorola-Q9c; Windows Mobile 6.1 Standard\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Mobile\",\n            \"version\" : \"6.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/windows-phone.json",
    "content": "[\n    {\n        \"desc\"    : \"Windows Phone\",\n        \"ua\"      : \"Opera/9.80 (Windows Phone; Opera Mini/7.6.8/35.7518; U; ru) Presto/2.8.119 Version/11.10\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Phone\",\n            \"version\" : \"undefined\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Phone 6.5\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HTC_Touch2_T3333; Windows Phone 6.5)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Phone\",\n            \"version\" : \"6.5\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Phone 7.0\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; DELL; Venue Pro)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Phone\",\n            \"version\" : \"7.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Phone 7.5\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 800)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Phone\",\n            \"version\" : \"7.5\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Phone 8\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; HTC; Windows Phone 8X by HTC)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Phone\",\n            \"version\" : \"8.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Phone 8.1\",\n        \"ua\"      : \"Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows Phone\",\n            \"version\" : \"8.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/windows-rt.json",
    "content": "[\n    {\n        \"desc\"    : \"Windows RT 8\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows RT\",\n            \"version\" : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows RT 8.1\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.3; ARM; Trident/7.0; Touch; rv:11.0) like Gecko\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows RT\",\n            \"version\" : \"8.1\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/windows.json",
    "content": "[\n    {\n        \"desc\"    : \"Windows 3.1\",\n        \"ua\"      : \"NCSA_Mosaic/2.0 (Windows 3.1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"3.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 3.1\",\n        \"ua\"      : \"Mozilla/1.22 (compatible; MSIE 2.0; Windows 3.1)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"3.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows NT\",\n        \"ua\"      : \"Mozilla/4.51 [de] (WinNT; I)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"NT\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows NT 3.51\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 4.0; Windows NT)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"NT\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows NT 3.51\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.05; Windows NT 3.51)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"NT 3.51\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows NT 4.0\",\n        \"ua\"      : \"Opera/8.41.(Windows NT 4.0; ts-ZA) Presto/2.9.178 Version/11.00\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"NT 4.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows NT 4.0\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.7.5) Gecko/20041108 Firefox/52.7.4\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"NT 4.0\"\n        }\n    },\n    {\n        \"desc\"    : \"Netscape on Windows 95\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win95; de-DE; rv:0.9.2) Gecko/20010726 Netscape6/6.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"95\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 95\",\n        \"ua\"      : \"Mozilla/3.0 (Win95)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"95\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 95\",\n        \"ua\"      : \"Mozilla/3.0 (compatible; Opera/3.0; Windows 95/NT4) 3.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"95\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 95\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.02 [en]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"95\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 95\",\n        \"ua\"      : \"Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"95\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 98\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"98\"\n        }\n    },\n    {\n        \"desc\"    : \"Firebird on Windows 98\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007 Firebird/0.7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"98\"\n        }\n    },\n    {\n        \"desc\"    : \"K-Meleon on Windows 98\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"98\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows ME\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win 9x 4.90) Gecko/20020502 CS 2000 7.0/7.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"ME\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera on Windows ME\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 5.12 [de]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"ME\"\n        }\n    },\n    {\n        \"desc\"    : \"Netscape on Windows ME\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8.1.8pre) Gecko/20071015 Firefox/2.0.0.7 Navigator/9.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"ME\"\n        }\n    },\n    {\n        \"desc\"    : \"Netscape on Windows 2000\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20050519 Netscape/8.0.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"2000\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera on Windows 2000\",\n        \"ua\"      : \"Opera/6.05 (Windows 2000; U)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"2000\"\n        }\n    },\n    {\n        \"desc\"    : \"Opera on Windows 2000\",\n        \"ua\"      : \"Opera/9.69 (Windows NT 5.01; en-US) Presto/2.8.160 Version/10.00\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"2000\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 2000\",\n        \"ua\"      : \"Mozilla/3.0 (compatible; MSIE 3.0; Windows NT 5.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"2000\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows XP\",\n        \"ua\"      : \"Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 5.2)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"XP\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows XP\",\n        \"ua\"      : \"Mozilla/5.0 (Windows XP; U) Opera 6.05  [de]\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"XP\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Vista\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; fr-FR)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"Vista\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 7\",\n        \"ua\"      : \"Microsoft Windows 7\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 7\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Evernote Windows/306387 (pt-PT, DDL); Windows/6.1.0 (Win32); Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 7\",\n        \"ua\"      : \"Mozilla/5.0 (Windows 7 Enterprise; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6099.71 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 7\",\n        \"ua\"      : \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 8\",\n        \"ua\"      : \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident/6.0; .NET4.0E; .NET4.0C)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 8.1\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:66.0.5) Gecko/20100101 Firefox/66.0.5\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"8.1\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows 10\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"Windows Server 2012 R2\",\n        \"ua\"      : \"Mozilla/5.0 (Windows Server 2012 R2 Standard; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5975.80 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"Server 2012 R2\"\n        }\n    },\n    {\n        \"desc\"    : \"WeChat Desktop for Windows Built-in Browser\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.901.400 QQBrowser/9.0.2524.400\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"WeChat Desktop for Windows Built-in Browser major version in 4\",\n        \"ua\"      : \"mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/81.0.4044.138 safari/537.36 nettype/wifi micromessenger/7.0.20.1781(0x6700143b) windowswechat\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows Vista\",\n        \"ua\"      : \"iTunes/10.7 (Windows; Microsoft Windows Vista Home Premium Edition Service Pack 1 (Build 6001)) AppleWebKit/536.26.9\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"Vista\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 7\",\n        \"ua\"      : \"iTunes/10.6.3 (Windows; Microsoft Windows 7 x64 Business Edition Service Pack 1 (Build 7601)) AppleWebKit/534.57.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"7\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 8\",\n        \"ua\"      : \"iTunes/12.1.1 (Windows; Microsoft Windows 8 x64 Business Edition (Build 9200)) AppleWebKit/7600.1017.9000.2\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"8\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 8.1\",\n        \"ua\"      : \"iTunes/12.4 (Windows; Microsoft Windows 8.1 x64 Business Edition (Build 9200); x64) AppleWebKit/7601.6016.1000.1\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"8.1\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 10\",\n        \"ua\"      : \"iTunes/12.9.1 (Windows; Microsoft Windows 10 x64 Professional Edition (Build 18362); x64) AppleWebKit/7606.2104.0.21\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 10\",\n        \"ua\"      : \"iTunes/12.6.3 (Windows; Microsoft Windows 10.0 x64 (Build 17763); x64) AppleWebKit/7604.1038.1006.6\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 10 S\",\n        \"ua\"      : \"iTunes/12.12 (Windows; Microsoft Windows 10 S x64; x64) AppleWebKit/7613.2007\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"10\"\n        }\n    },\n    {\n        \"desc\"    : \"iTunes on Windows 11\",\n        \"ua\"      : \"iTunes/12.13 (Windows; Microsoft Windows 11 x64; x64) AppleWebKit/7613.2007\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Windows\",\n            \"version\" : \"11\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/xbox.json",
    "content": "[\n    {\n        \"desc\"    : \"Xbox 360\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox 360) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xbox\",\n            \"version\" : \"360\"\n        }\n    },\n    {\n        \"desc\"    : \"Xbox One\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19041\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xbox\",\n            \"version\" : \"One\"\n        }\n    },\n    {\n        \"desc\"    : \"Xbox X\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/20.02\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xbox\",\n            \"version\" : \"X\"\n        }\n    },\n    {\n        \"desc\"    : \"Xbox Series X\",\n        \"ua\"      : \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox Series X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/20.02 \",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xbox\",\n            \"version\" : \"Series X\"\n        }\n    },\n    {\n        \"desc\"    : \"Xbox Series S\",\n        \"ua\"      : \"Mozilla/5.0 (Compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Xbox; Xbox Series S)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xbox\",\n            \"version\" : \"Series S\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/xubuntu.json",
    "content": "[\n    {\n        \"desc\"    : \"Xubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Xubuntu Linux 21.10 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.57 Vivaldi/5.1.2 (Blink)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xubuntu\",\n            \"version\" : \"21.10\"\n        }\n    },\n    {\n        \"desc\"    : \"Xubuntu\",\n        \"ua\"      : \"Mozilla/5.0 (X11; Xubuntu 14.04.5 LTS) AppleWebKit/537.36 (KHTML, like Gecko) Xubuntu Chrome/66.0.2623.87 Safari/537.36\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Xubuntu\",\n            \"version\" : \"14.04.5\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua/os/zenwalk.json",
    "content": "[\n    {\n        \"desc\"    : \"Zenwalk\",\n        \"ua\"      : \"Flock/2.16 (Zenwalk 7.3; es_PR;)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Zenwalk\",\n            \"version\" : \"7.3\"\n        }\n    },\n    {\n        \"desc\"    : \"Zenwalk\",\n        \"ua\"      : \"Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.13) Gecko/20101221 IceCat/3.6.13 (like Firefox/3.6.13) (Zenwalk GNU Linux)\",\n        \"expect\"  :\n        {\n            \"name\"    : \"Zenwalk\",\n            \"version\" : \"undefined\"\n        }\n    }\n]"
  },
  {
    "path": "test/data/ua-ch/headers.js",
    "content": "const UACHTests = [\n    {\n        desc: 'Avast Secure Browser',\n        headers : {\n            'sec-ch-ua': '\"Avast Secure Browser\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"'\n        },\n        expect: {\n            browser : {\n                name : 'Avast Secure Browser',\n                version : '131',\n                major : '131',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'AVG Secure Browser',\n        headers : {\n            'sec-ch-ua': '\"AVG Secure Browser\";v=\"123\", \"Not:A-Brand\";v=\"8\", \"Chromium\";v=\"123\"'\n        },\n        expect: {\n            browser : {\n                name : 'AVG Secure Browser',\n                version : '123',\n                major : '123',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Avira Secure Browser',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"124\", \"Avira Secure Browser\";v=\"124\", \"Not-A.Brand\";v=\"99\"'\n        },\n        expect: {\n            browser : {\n                name : 'Avira Secure Browser',\n                version : '124',\n                major : '124',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Brave',\n        headers : {\n            'sec-ch-ua': '\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Brave\";v=\"132\"'\n        },\n        expect: {\n            browser : {\n                name : 'Brave',\n                version : '132',\n                major : '132',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Chrome',\n        headers : {\n            'sec-ch-ua': '\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"'\n        },\n        expect: {\n            browser : {\n                name : 'Chrome',\n                version : '111',\n                major : '111',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Chrome Headless',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"124\", \"HeadlessChrome\";v=\"124\", \"Not-A.Brand\";v=\"99\"'\n        },\n        expect: {\n            browser : {\n                name : 'Chrome Headless',\n                version : '124',\n                major : '124',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Chrome WebView',\n        headers : {\n            'sec-ch-ua': '\"Android WebView\";v=\"123\", \"Not:A-Brand\";v=\"8\", \"Chromium\";v=\"123\"'\n        },\n        expect: {\n            browser : {\n                name : 'Chrome WebView',\n                version : '123',\n                major : '123',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'DuckDuckGo',\n        headers : {\n            'sec-ch-ua': '\"DuckDuckGo\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"'\n        },\n        expect : {\n            browser : {\n                name : 'DuckDuckGo',\n                version : '131',\n                major : '131',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Edge',\n        headers : {\n            'sec-ch-ua': '\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Microsoft Edge\";v=\"120\"'\n        },\n        expect: {\n            browser : {\n                name : 'Edge',\n                version : '120',\n                major : '120',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Edge WebView2',\n        headers : {\n            'sec-ch-ua': '\" Not;A Brand\";v=\"99\", \"Microsoft Edge\";v=\"103\", \"Chromium\";v=\"103\", \"Microsoft Edge WebView2\";v=\"104\"'\n        },\n        expect: {\n            browser : {\n                name : 'Edge WebView2',\n                version : '104',\n                major : '104',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Huawei Browser',\n        headers : {\n            'sec-ch-ua': '\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"HuaweiBrowser\";v=\"114\"'\n        },\n        expect: {\n            browser : {\n                name : 'Huawei Browser',\n                version : '114',\n                major : '114',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Lighthouse',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"119\", \"Google Chrome\";v=\"119\", \"Lighthouse\";v=\"11.5.0\"'\n        },\n        expect: {\n            browser : {\n                name : 'Lighthouse',\n                version : '11.5.0',\n                major : '11',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'MIUI Browser',\n        headers : {\n            'sec-ch-ua': '\"Miui Browser\";v=\"123\", \"Not:A-Brand\";v=\"8\", \"Chromium\";v=\"123\"'\n        },\n        expect: {\n            browser : {\n                name : 'MIUI Browser',\n                version : '123',\n                major : '123',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Norton Private Browser',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"124\", \"Norton Private Browser\";v=\"124\", \"Not-A.Brand\";v=\"99\"'\n        },\n        expect: {\n            browser : {\n                name : 'Norton Private Browser',\n                version : '124',\n                major : '124',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Oculus Browser',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"130\", \"Oculus Browser\";v=\"36\", \"Not?A_Brand\";v=\"99\"'\n        },\n        expect: {\n            browser : {\n                name : 'Oculus Browser',\n                version : '36',\n                major : '36',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Opera',\n        headers : {\n            'sec-ch-ua': '\"Opera\";v=\"116\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"'\n        },\n        expect: {\n            browser : {\n                name : 'Opera',\n                version : '116',\n                major : '116',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Opera GX',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"128\", \"Not;A=Brand\";v=\"24\", \"Opera GX\";v=\"114\"'\n        },\n        expect: {\n            browser : {\n                name : 'Opera GX',\n                version : '114',\n                major : '114',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Opera Mobi',\n        headers : {\n            'sec-ch-ua': '\"OperaMobile\";v=\"86\", \";Not A Brand\";v=\"99\", \"Opera\";v=\"115\", \"Chromium\";v=\"130\"'\n        },\n        expect: {\n            browser : {\n                name : 'Opera Mobi',\n                version : '86',\n                major : '86',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Opera Mobi',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"132\", \"OperaMobile\";v=\"87\", \"Opera\";v=\"117\", \" Not A;Brand\";v=\"99\"'\n        },\n        expect: {\n            browser : {\n                name : 'Opera Mobi',\n                version : '87',\n                major : '87',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Samsung Internet',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"125\", \"Not.A/Brand\";v=\"24\", \"Samsung Internet\";v=\"27.0\"'\n        },\n        expect: {\n            browser : {\n                name : 'Samsung Internet',\n                version : '27.0',\n                major : '27',\n                type : undefined\n            }\n        }\n    },\n    {\n        desc: 'Yandex',\n        headers : {\n            'sec-ch-ua': '\"Chromium\";v=\"130\", \"YaBrowser\";v=\"24.12\", \"Not?A_Brand\";v=\"99\", \"Yowser\";v=\"2.5\"'\n        },\n        expect: {\n            browser : {\n                name : 'Yandex',\n                version : '24.12',\n                major : '24',\n                type : undefined\n            }\n        }\n    }\n];\n\nmodule.exports = UACHTests;"
  },
  {
    "path": "test/e2e/browser.spec.mjs",
    "content": "import { test, expect } from '@playwright/test';\nimport path from 'path';\nimport url from 'url';\n\nconst localHtml = `file://${path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '../../')}/dist/ua-parser.html`;\nconst browserMap = {\n    chromium: 'Chrome Headless',\n    firefox: 'Firefox',\n    webkit: 'Safari'\n}\n\ntest.describe('Custom navigator.userAgent tests', () => {\n\n    test('Undefined navigator.userAgent regarded as an empty user-agent string', async ({ page }) => {\n        await page.addInitScript(() => {\n            Object.defineProperty(navigator, 'userAgent', {\n                value: undefined\n            });\n        });\n        await page.goto(localHtml);\n        // @ts-ignore\n        const uap = await page.evaluate(async () => await UAParser());\n        expect(uap).toHaveProperty('ua', '');\n        expect(uap).toHaveProperty('browser.name', undefined);\n    });\n});\n\ntest.describe('User-defined user-agent tests', () => {\n\n    test.beforeEach(async ({ page }) => {\n        await page.goto(localHtml);\n    });\n\n    test('Accept empty user-agent', async ({ page }) => {\n        // @ts-ignore\n        const uap = await page.evaluate(async () => await UAParser(''));\n        expect(uap).toHaveProperty('ua', '');\n    });\n\n    test('Truncate very long user-agent', async ({ page }) => {\n        // @ts-ignore\n        const uap = await page.evaluate(async () => await UAParser('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; 66760635803; runtime 11.00294; 876906799603; 97880703; 669602703; 9778063903; 877905603; 89670803; 96690803; 8878091903; 7879040603; 999608065603; 799808803; 6666059903; 669602102803; 888809342903; 696901603; 788907703; 887806555703; 97690214703; 66760903; 968909903; 796802422703; 8868026703; 889803611803; 898706903; 977806408603; 976900799903; 9897086903; 88780803; 798802301603; 9966008603; 66760703; 97890452603; 9789064803; 96990759803; 99960107703; 8868087903; 889801155603; 78890703; 8898070603; 89970603; 89970539603; 89970488703; 8789007603; 87890903; 877904603; 9887077703; 798804903; 97890264603; 967901703; 87890703; 97690420803; 79980706603; 9867086703; 996602846703; 87690803; 6989010903; 977809603; 666601903; 876905337803; 89670603; 89970200903; 786903603; 696901911703; 788905703; 896709803; 96890703; 998601903; 88980703; 666604769703; 978806603; 7988020803; 996608803; 788903297903; 98770043603; 899708803; 66960371603; 9669088903; 69990703; 99660519903; 97780603; 888801803; 9867071703; 79780803; 9779087603; 899708603; 66960456803; 898706824603; 78890299903; 99660703; 9768079803; 977901591603; 89670605603; 787903608603; 998607934903; 799808573903; 878909603; 979808146703; 9996088603; 797803154903; 69790603; 99660565603; 7869028603; 896707703; 97980965603; 976907191703; 88680703; 888809803; 69690903; 889805523703; 899707703; 997605035603; 89970029803; 9699094903; 877906803; 899707002703; 786905857603; 69890803; 97980051903; 997603978803; 9897097903; 66960141703; 7968077603; 977804603; 88980603; 989700803; 999607887803; 78690772803; 96990560903; 98970961603; 9996032903; 9699098703; 69890655603; 978903803; 698905066803; 977806903; 9789061703; 967903747703; 976900550903; 88980934703; 8878075803; 8977028703; 97980903; 9769006603; 786900803; 98770682703; 78790903; 878906967903; 87690399603; 99860976703; 796805703; 87990603; 968906803; 967904724603; 999606603; 988705903; 989702842603; 96790603; 99760703; 88980166703; 9799038903; 98670903; 697905248603; 7968043603; 66860703; 66860127903; 9779048903; 89670123903; 78890397703; 97890603; 87890803; 8789030603; 69990603; 88880763703; 9769000603; 96990203903; 978900405903; 7869022803; 699905422903; 97890703; 87990903; 878908703; 7998093903; 898702507603; 97780637603; 966907903; 896702603; 9769004803; 7869007903; 99660158803; 7899099603; 8977055803; 99660603; 7889080903; 66660981603; 997604603; 6969089803; 899701903; 9769072703; 666603903; 99860803; 997608803; 69790903; 88680756703; 979805677903; 9986047703; 89970803; 66660603; 96690903; 8997051603; 789901209803; 8977098903; 968900326803; 87790703; 98770024803; 697901794603; 69990803; 887805925803; 968908903; 97880603; 897709148703; 877909476903; 66760197703; 977908603; 698902703; 988706504803; 977802026603; 88680964703; 8878068703; 987705107903; 978902878703; 8898069803; 9768031703; 79680803; 79980803; 669609328703; 89870238703; 99960593903; 969904218703; 78890603; 9788000703; 69690630903; 889800982903; 988709748803; 7968052803; 99960007803; 969900800803; 668604817603; 66960903; 78790734603; 8868007703; 79780034903; 8878085903; 976907603; 89670830803; 877900903; 969904889703; 7978033903; 8987043903; 99860703; 979805903; 667603803; 976805348603; 999604127603; 97790701603; 78990342903; 98770672903; 87990253903; 9877027703; 97790803; 877901895603; 8789076903; 896708595603; 997601903; 799806903; 97690603; 87790371703; 667605603; 99760303703; 97680283803; 788902750803; 787909803; 79780603; 79880866903; 9986050903; 87890543903; 979800803; 97690179703; 876901603; 699909903; 96990192603; 878904903; 877904734903; 796801446903; 977904803; 9887044803; 797805565603; 98870789703; 7869093903; 87790727703; 797801232803; 666604803; 9778071903; 9799086703; 6969000903; 89670903; 8799075903; 897708903; 88680903; 97980362603; 97980503903; 889803256703; 88980388703; 789909376803; 69690703; 6969025903; 89970309903; 96690703; 877901847803; 968901903; 96690603; 88680607603; 7889001703; 789904761803; 976807703; 976902903; 878907889703; 9897014903; 896707046603; 696909903; 666603998903; 969902703; 79680421803; 9769075603; 798800192703; 97990903; 9689024903; 668604803; 969908671903; 9996094703; 69990642703; 97890895903; 977805619903; 79980859903; 88980443803; 98970649603; 997602703; 888802169903; 699907803; 667602028803; 786903283903; 997607703; 969909803; 798809925903; 9976045603; 97790903; 9789001903; 966903603; 9789069603; 968906603; 6989091803; 896701603; 6979059803; 978803903; 997606362603; 88980803; 98970803; 88880921703; 8997065703; 899700703; 698908703; 797801027903; 7889050903; 87890603; 78690703; 99660069703; 97980309903; 976800603; 666606803; 898707703; 79880019803; 66960250803; 7978049803; 88780602603; 79680903; 88880792703; 96990903; 667608603; 87790730903; 98970903; 9699032903; 8987004803; 88880703; 89770046603; 978800803; 969908903; 9798022603; 696901903; 799803703; 989703703; 668605903; 79780903; 998601371703; 796803339703; 87890922603; 898708903; 9966061903; 66960891903; 96790903; 8779050803; 98870858803; 976909298603; 9887029903; 669608703; 979806903; 878903803; 99960703; 9789086703; 979801803; 66960008703; 979806830803; 99760212703; 786906603; 797807603; 789907297703; 96990703; 786901603; 796807766603; 896702651603; 789902585603; 66660925903; 9986085703; 66960302703; 69890703; 789900703; 89970903; 9679060703; 9789002903; 979908821603; 986708140803; 976809828703; 7988082803; 79680997903; 99960803; 9788081903; 979805703; 787908603; 66960602803; 9887098703; 978803237703; 888806804603; 999604703; 977904703; 966904635703; 97680291703; 977809345603; 8878046703; 988709803; 976900773603; 989703903; 88780198603; 87790603; 986708703; 78890604703; 87790544803; 976809850903; 887806703; 987707527603; 79880803; 9897059603; 897709820603; 97880804803; 66960026703; 9789062803; 9867090803; 669600603; 8967087703; 78890903; 89770903; 97980703; 976802687603; 66860400803; 979901288603; 96990160903; 99860228903; 966900703; 66760603; 9689035703; 9779064703; 7968023603; 87890791903; 98770870603; 9798005803; 6969087903; 9779097903; 6979065703; 699903252603; 79780989703; 87690901803; 978905763903; 977809703; 97790369703; 899703269603; 8878012703; 78790803; 87690395603; 8888042803; 667607689903; 8977041803; 6666085603; 6999080703; 69990797803; 88680721603; 99660519803; 889807603; 87890146703; 699906325903; 89770603; 669608615903; 9779028803; 88880603; 97790703; 79780703; 97680355603; 6696024803; 78790784703; 97880329903; 9699077703; 89870803; 79680227903; 976905852703; 8997098903; 896704796703; 66860598803; 9897036703; 66960703; 9699094703; 9699008703; 97780485903; 999603179903; 89770834803; 96790445603; 79680460903; 9867009603; 89870328703; 799801035803; 989702903; 66960758903; 66860150803; 6686088603; 9877092803; 96990603; 99860603; 987703663603; 98870903; 699903325603; 87790803; 97680703; 8868030703; 9799030803; 89870703; 97680803; 9669054803; 6979097603; 987708046603; 999608603; 878904803; 998607408903; 968903903; 696900703; 977907491703; 6686033803; 669601803; 99960290603; 887809169903; 979803703; 69890903; 699901447903; 8987064903; 799800603; 98770903; 8997068703; 967903603; 66760146803; 978805087903; 697908138603; 799801603; 88780964903; 989708339903; 8967048603; 88880981603; 789909703; 796806603; 977905977603; 989700603; 97780703; 9669062603; 88980714603; 897709545903; 988701916703; 667604694903; 786905664603; 877900803; 886805490903; 89970559903; 99960531803; 7998033903; 98770803; 78890418703; 669600872803; 996605216603; 78690962703; 667604903; 996600903; 999608903; 9699083803; 787901803; 97780707603; 787905312703; 977805803; 8977033703; 97890708703; 989705521903; 978800703; 698905703; 78890376903; 878907703; 999602903; 986705903; 668602719603; 979901803; 997606903; 66760393903; 987703603; 78790338903; 96890803; 97680596803; 666601603; 977902178803; 877902803; 78790038603; 8868075703; 99960060603)'));\n\n        expect(uap).toHaveProperty('ua', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; 66760635803; runtime 11.00294; 876906799603; 97880703; 669602703; 9778063903; 877905603; 89670803; 96690803; 8878091903; 7879040603; 999608065603; 799808803; 6666059903; 669602102803; 888809342903; 696901603; 788907703; 887806555703; 97690214703; 66760903; 968909903; 796802422703; 8868026703; 8898036');\n    });\n});\n\ntest.describe('withClientHints() tests', () => {\n\n    test('Detect custom Client Hints data', async ({ page, browserName }) => {        \n        await page.addInitScript((browserName) => {\n            if (browserName == 'chromium') {\n                Object.defineProperty(navigator, 'userAgentData', {\n                    value: {\n                        brands: [],\n                        platform: '',\n                        mobile: false,\n                        getHighEntropyValues: () => {\n                            return Promise.resolve({\n                                brands: [\n                                    {\n                                        brand: 'Chromium',\n                                        version: '110'\n                                    },\n                                    {\n                                        brand: 'Not(A:Brand',\n                                        version: '110'\n                                    },\n                                    {\n                                        brand: 'New Browser',\n                                        version: '110'\n                                    }\n                                ],\n                                platform: 'New OS',\n                                formFactors: 'New Form Factor'\n                            });\n                        }\n                    }\n                });\n            }\n        }, browserName);\n        await page.goto(localHtml);\n        // @ts-ignore\n        const uap = await page.evaluate(async () => await UAParser().withClientHints());\n        if (browserName == 'chromium') {\n            expect(uap).toHaveProperty('browser.name', 'New Browser');\n            expect(uap).toHaveProperty('os.name', 'New OS');\n            expect(uap).toHaveProperty('device.type', undefined);\n        } else {\n            expect(uap).toHaveProperty('browser.name', browserMap[browserName]);\n        }\n    });\n});\n\ntest.describe('withFeatureCheck() tests', () => {\n\n    test('Detect Brave', async ({ page, browserName }) => {\n        await page.addInitScript(() => {\n            Object.defineProperty(navigator, 'brave', {\n                value: {\n                    isBrave: () => true\n                }\n            });\n        });\n        await page.goto(localHtml);\n        // @ts-ignore\n        let uap = await page.evaluate(() => UAParser());\n        expect(uap).toHaveProperty('browser.name', browserMap[browserName]);\n        // @ts-ignore\n        uap = await page.evaluate(() => UAParser().withFeatureCheck());\n        expect(uap).toHaveProperty('browser.name', 'Brave');\n    });\n\n\n    test('Detect iPad', async ({ page }) => {\n        await page.addInitScript(() => {\n            Object.defineProperty(navigator, 'userAgent', {\n                value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15'\n            });\n            Object.defineProperty(navigator, 'standalone', {\n                value: true\n            });\n            Object.defineProperty(navigator, 'maxTouchPoints', {\n                value: 3\n            });\n        });\n        await page.goto(localHtml);\n        // @ts-ignore\n        let uap = await page.evaluate(() => UAParser());\n        expect(uap).toHaveProperty('device.model', 'Macintosh');\n        expect(uap).toHaveProperty('device.type', undefined);\n        // @ts-ignore\n        uap = await page.evaluate(() => UAParser().withFeatureCheck());\n        expect(uap).toHaveProperty('device.model', 'iPad');\n        expect(uap).toHaveProperty('device.type', 'tablet');\n    });\n});\n\ntest.describe('request.headers can be passed in form of a Headers object', () => {\n\n    test('Headers automatically converted into a plain key-value object', async ({ page }) => {\n        await page.addInitScript(() => {\n            Object.defineProperty(window, 'req', {\n                value : {\n                    headers: new Headers([[\"User-Agent\", \"myBrowser/1.0\"]])\n                }\n            });\n        });\n        await page.goto(localHtml);\n        // @ts-ignore\n        const uap = await page.evaluate(() => UAParser(req.headers));\n        expect(uap.ua).toBe('myBrowser/1.0');\n    });\n});\n\ntest.describe('Chaining withFeatureCheck() & withClientHints() in client-side development', () => {\n\n    test('Chain', async ({ page, browserName }) => {   \n        await page.addInitScript((browserName) => {\n            Object.defineProperty(navigator, 'userAgent', {\n                value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15'\n            });\n            Object.defineProperty(navigator, 'standalone', {\n                value: true\n            });\n            Object.defineProperty(navigator, 'maxTouchPoints', {\n                value: 3\n            });\n            if (browserName == 'chromium') {\n                Object.defineProperty(navigator, 'userAgentData', {\n                    value: {\n                        brands: [],\n                        platform: '',\n                        mobile: false,\n                        getHighEntropyValues: () => {\n                            return Promise.resolve({\n                                formFactors: 'VR'\n                            });\n                        }\n                    }\n                });\n            }\n        }, browserName);\n        await page.goto(localHtml);\n        // @ts-ignore\n        const fc2ch = await page.evaluate(async () => await UAParser().withFeatureCheck().then(res => res.withClientHints()));\n        const ch2fc = await page.evaluate(async () => await UAParser().withClientHints().then(res => res.withFeatureCheck()));\n        if (browserName == 'chromium') {\n            expect(fc2ch).toHaveProperty('device.type', 'xr');      // overwrite by client hints\n            expect(ch2fc).toHaveProperty('device.type', 'tablet');  // overwrite by feature check\n        } else {\n            expect(fc2ch).toHaveProperty('device.type', 'tablet');  // no client hints found\n            expect(ch2fc).toHaveProperty('device.type', 'tablet');\n        }\n    });\n});"
  },
  {
    "path": "test/fuzz/redos.js",
    "content": "const { FuzzedDataProvider } = require('@jazzer.js/core');\nconst { UAParser } = require('../../dist/main');\nconst UA_MAX_LENGTH = 500;\n\nmodule.exports.fuzz = function (buffer) {\n    const data = new FuzzedDataProvider(buffer);\n    const userAgent = data.consumeString(UA_MAX_LENGTH, 'utf-8', true);\n    const start = process.hrtime();\n    \n    UAParser(userAgent);\n\n    const elapsed = process.hrtime(start);\n    const milisec = (elapsed[0]*1e3+elapsed[1]*1e-6).toFixed(3);\n    if (milisec > 1000) {\n        throw new Error(\n            `Potential ReDoS\\n` +\n            `Time taken: ${milisec} ms.\\n` +\n            `User agent: ${userAgent}`);\n    }\n};"
  },
  {
    "path": "test/static/dts-lint.ts",
    "content": "import { expectType } from 'tsd';\nimport { UAParser, IResult, IBrowser, ICPU, IEngine, IDevice, IOS } from \"../../src/main/ua-parser\";\nimport { isAppleSilicon, isChromeFamily } from \"../../src/helpers/ua-parser-helpers\";\n\nconst uastring = 'Mozilla/5.0 (X11; MyCustomOS; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0';\nconst extensions = {\n    os : [\n        [/(mycustomos)/], [UAParser.OS.NAME, [UAParser.OS.VERSION, '10']]\n    ]\n};\nconst headers = {\n    'sec-ch-ua-mobile' : '?1'\n};\n\nexpectType<IResult>(UAParser());\nexpectType<IResult>(UAParser(uastring));\nexpectType<IResult>(UAParser(uastring, extensions));\nexpectType<IResult>(UAParser(uastring, headers));\nexpectType<IResult>(UAParser(extensions, headers));\nexpectType<IResult>(UAParser(extensions));\nexpectType<IResult>(UAParser(headers));\nexpectType<UAParser>(new UAParser());\n\nconst parser = new UAParser(uastring);\nconst browser = parser.getBrowser();\n\nexpectType<IBrowser>(browser);\nexpectType<string | undefined>(browser.name);\nexpectType<string | undefined>(browser.version);\nexpectType<string | undefined>(browser.major);\nexpectType<'crawler' | 'cli' | 'email' | 'fetcher' | 'inapp' | 'mediaplayer' | 'library' | undefined>(browser.type);\nexpectType<boolean>(browser.is(''));\nexpectType<string>(browser.toString());\nexpectType<IBrowser | PromiseLike<IBrowser>>(browser.withClientHints());\nexpectType<IBrowser | PromiseLike<IBrowser>>((<IBrowser>browser.withClientHints()).withFeatureCheck());\nexpectType<boolean>((<IBrowser>(<IBrowser>browser.withClientHints()).withFeatureCheck()).is(''));\n\nexpectType<ICPU>(parser.getCPU());\nexpectType<IDevice>(parser.getDevice());\nexpectType<IEngine>(parser.getEngine());\nexpectType<IOS>(parser.getOS());\nexpectType<IResult>(parser.getResult());\nexpectType<string>(parser.getUA());\nexpectType<UAParser>(parser.setUA(uastring));\n\nconst result = parser.getResult();\n\nexpectType<boolean>(isAppleSilicon(result));\nexpectType<boolean>(isChromeFamily(result));"
  },
  {
    "path": "test/unit/cli/cli.spec.js",
    "content": "const assert = require('node:assert');\nconst { exec } = require('node:child_process');\nconst fs = require('node:fs');\nconst { UAParser } = require('../../../src/main/ua-parser');\nconst uap = new UAParser();\n\nconst input = [\n    'Opera/9.25 (Windows NT 6.0; U; ru)',\n    'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'\n];\nconst output = input.map(x => uap.setUA(x).getResult());\n\ndescribe('npx ua-parser-js <string>', () => {\n    it ('print result to stdout', () => {\n        exec('npx ua-parser-js \"TEST\"', (err, stdout, stderr) => {\n            assert.deepEqual(JSON.parse(stdout), JSON.parse(JSON.stringify([uap.setUA(\"TEST\").getResult()])));\n        });\n    })\n});\n\ndescribe('npx ua-parser-js --input-file=<filepath>', () => {\n    it ('load file and print result to stdout', () => {\n        exec('npx ua-parser-js --input-file=\"../test/unit/cli/input.txt\"', (err, stdout, stderr) => {\n            assert.deepEqual(JSON.parse(stdout), JSON.parse(JSON.stringify(output)));\n        });\n    });\n});\n\ndescribe('npx ua-parser-js --input-file=<filepath> --output-file=<filepath>', () => {\n    it ('load file and save result to file', () => {\n        exec('npx ua-parser-js --input-file=\"../test/unit/cli/input.txt\" --output-file=\"../test/unit/cli/output.json\"', (err, stdout, stderr) => {\n            fs.readFile('test/unit/cli/output.json', (err, data) => {\n                assert.deepEqual(JSON.parse(data), JSON.parse(JSON.stringify(output)));\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/cli/input.txt",
    "content": "Opera/9.25 (Windows NT 6.0; U; ru)\nMozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
  },
  {
    "path": "test/unit/cli/output.json",
    "content": "[\n{\n    \"ua\": \"Opera/9.25 (Windows NT 6.0; U; ru)\",\n    \"browser\": {\n        \"name\": \"Opera\",\n        \"version\": \"9.25\",\n        \"major\": \"9\"\n    },\n    \"cpu\": {},\n    \"device\": {},\n    \"engine\": {},\n    \"os\": {\n        \"name\": \"Windows\",\n        \"version\": \"Vista\"\n    }\n},\n{\n    \"ua\": \"Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)\",\n    \"browser\": {\n        \"name\": \"IE\",\n        \"version\": \"5.5\",\n        \"major\": \"5\"\n    },\n    \"cpu\": {},\n    \"device\": {},\n    \"engine\": {},\n    \"os\": {\n        \"name\": \"Windows\",\n        \"version\": \"NT\"\n    }\n}\n]"
  },
  {
    "path": "test/unit/es6.mjs",
    "content": "import { UAParser } from '../../src/main/ua-parser.mjs';\nimport { CPUArch, DeviceType, EngineName } from '../../src/enums/ua-parser-enums.mjs';\nimport * as assert from 'assert';\n\ndescribe('Returns', () => {\n    it('getResult() should returns object', () => {\n        assert.deepEqual(new UAParser('').getResult(), \n            {\n                ua : '',\n                browser: { name: undefined, version: undefined, major: undefined, type: undefined },\n                cpu: { architecture: undefined },\n                device: { vendor: undefined, model: undefined, type: undefined },\n                engine: { name: undefined, version: undefined},\n                os: { name: undefined, version: undefined }\n        });\n    });\n});\n\ndescribe('Enums', () => {    \n    it('Can use enum', () => {\n        const { cpu, device, engine } = UAParser('Mozilla/5.0 (X11; U; Linux armv7l; en-GB; rv:1.9.2a1pre) Gecko/20090928 Firefox/3.5 Maemo Browser 1.4.1.22 RX-51 N900');\n        assert.strictEqual(cpu.is(CPUArch.ARM), true);\n        assert.strictEqual(device.is(DeviceType.MOBILE), true);\n        assert.strictEqual(engine.is(EngineName.GECKO), true);\n    });\n});"
  },
  {
    "path": "test/unit/main.js",
    "content": "var fs          = require('fs');\nvar safe        = require('safe-regex');\nvar assert      = require('assert');\nvar requirejs   = require('requirejs');\nvar parseJS     = require('@babel/parser').parse;\nvar traverse    = require('@babel/traverse').default;\nvar {UAParser}  = require('../../src/main/ua-parser');\nvar {CLIs}      = require('../../src/extensions/ua-parser-extensions');\nvar {Extension} = require('../../src/enums/ua-parser-enums');\nvar browsers    = require('../data/ua/browser/browser-all.json');\nvar cpus        = require('../data/ua/cpu/cpu-all.json');\nvar devices     = readJsonFiles('test/data/ua/device');\nvar engines     = require('../data/ua/engine/engine-all.json');\nvar os          = readJsonFiles('test/data/ua/os');\n\nfunction readJsonFiles(dir) {\n    var list = [];\n    fs.readdirSync(dir).forEach(function (file) {\n        list.push(...JSON.parse(fs.readFileSync(`${dir}/${file}`, 'utf-8')));\n    });\n    return list;\n};\n\ndescribe('UAParser()', function () {\n    var ua = 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6';\n    assert.deepEqual(UAParser(ua), new UAParser().setUA(ua).getResult());\n});\n\ndescribe('UAParser() constructor does not throw with undefined ua argument', function () {\n    assert.doesNotThrow(() => new UAParser(undefined).getResult());\n});\n\ndescribe('UAParser.setUA method does not throw with undefined ua argument', function () {\n    assert.doesNotThrow(() => new UAParser().setUA(undefined).getResult());\n});\n\ndescribe('UAParser get*() methods', () => {\n    [\n        {\n            title       : 'getBrowser()',\n            label       : 'browser',\n            list        : browsers\n        },\n        {\n            title       : 'getCPU()',\n            label       : 'cpu',\n            list        : cpus\n        },\n        {\n            title       : 'getDevice()',\n            label       : 'device',\n            list        : devices\n        },\n        {\n            title       : 'getEngine()',\n            label       : 'engine',\n            list        : engines\n        },\n        {\n            title       : 'getOS()',\n            label       : 'os',\n            list        : os\n        }\n    ]\n    .forEach(method => {\n        describe(`[${method.title}]`, () => {\n            method.list.forEach(unit => {\n                describe(`[${unit.desc}]: \"${unit.ua}\"`, () => {\n                    const actual = UAParser(unit.ua)[method.label];\n                    Object.entries(unit.expect).forEach(entry => {\n                        const [key, val] = entry;\n                        it(`Should return ${key}: ${val}`, () => {\n                            assert.strictEqual(String(val), String(actual[key]));\n                        });\n                    });\n                });\n            });\n        });\n    });\n});\n\ndescribe('Returns', function () {\n    it('getResult() should returns JSON', function(done) {\n        assert.deepEqual(new UAParser('').getResult(), \n            {\n                ua : '',\n                browser: { name: undefined, version: undefined, major: undefined, type: undefined },\n                cpu: { architecture: undefined },\n                device: { vendor: undefined, model: undefined, type: undefined },\n                engine: { name: undefined, version: undefined},\n                os: { name: undefined, version: undefined }\n        });\n        done();\n    });\n\n    it('works even when Array.prototype has been mangled', function(done) {\n        const result = withMangledArrayProto(() => new UAParser('').getResult());\n\n        function withMangledArrayProto(fn, key = 'isEmpty', value = function() { return this.length === 0; }) {\n            const originalValue = Array.prototype[key];\n            const restore = Object.hasOwnProperty.call(Array.prototype, key)\n                ? () => Array.prototype[key] = originalValue\n                : () => delete Array.prototype[key];\n\n            Array.prototype[key] = value;\n            const result = fn();\n            restore();\n\n            return result;\n        }\n\n        assert.deepEqual(result,\n            {\n                ua : '',\n                browser: { name: undefined, version: undefined, major: undefined, type: undefined },\n                cpu: { architecture: undefined },\n                device: { vendor: undefined, model: undefined, type: undefined },\n                engine: { name: undefined, version: undefined},\n                os: { name: undefined, version: undefined }\n        });\n        done();\n    });\n});\n\n\ndescribe('setExtension()', () => {\n    \n    it('Extends default parser', () => {\n        const uap = new UAParser();\n        uap.setUA('Mozilla/5.0 (Windows NT; Windows NT 10.0; de-DE) WindowsPowerShell/5.1.19041.5737');\n\n        // before useExtension()\n        assert.strictEqual(uap.getBrowser().name, undefined);           \n        \n        // after useExtension()\n        uap.useExtension(CLIs);\n        assert.strictEqual(uap.getBrowser().name, Extension.BrowserName.CLI.POWERSHELL);\n    });\n\n    it('Prioritize last input', () => {\n        const ext1 = { browser : [[/MyBrowzer/], [[UAParser.BROWSER.NAME, 'Foo']]] };\n        const ext2 = { browser : [[/MyBrowzer/], [[UAParser.BROWSER.NAME, 'Bar']]] };\n        const uap = new UAParser();\n\n        uap\n          .setUA('MyBrowzer')\n          .useExtension(ext1)\n          .useExtension(ext2);\n        \n        assert.strictEqual(uap.getBrowser().name, 'Bar');\n    });\n});\n\ndescribe('Extending Regex', function () {\n    var uaString = 'Mozilla/5.0 MyOwnBrowser/1.3';\n    var myOwnBrowser = [[/(myownbrowser)\\/((\\d+)?[\\w\\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, UAParser.BROWSER.MAJOR]];\n\n    var parser1 = new UAParser(uaString, {browser: myOwnBrowser});\n    assert.strictEqual(parser1.getBrowser().name, 'MyOwnBrowser');\n    assert.strictEqual(parser1.getBrowser().version, '1.3');\n    assert.strictEqual(parser1.getBrowser().major, '1');\n\n    var parser2 = new UAParser({browser: myOwnBrowser});\n    assert.strictEqual(parser2.getBrowser().name, undefined);\n    parser2.setUA(uaString);\n    assert.strictEqual(parser2.getBrowser().name, 'MyOwnBrowser');\n    assert.strictEqual(parser1.getBrowser().version, '1.3');\n\n    let myOwnListOfBrowsers = [\n        [/(mybrowser)\\/([\\w\\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']]\n    ];\n    let myParser = new UAParser({ browser: myOwnListOfBrowsers });\n    let myUA = 'Mozilla/5.0 MyBrowser/1.3';\n    assert.deepEqual(myParser.setUA(myUA).getBrowser(), {name: \"MyBrowser\", version: \"1.3\", major: \"1\", type : \"bot\"});\n    assert.strictEqual(myParser.getBrowser().is('bot'), true);\n    \n    let myOwnListOfDevices = [\n        [/(mytab) ([\\w ]+)/i], [UAParser.DEVICE.VENDOR, UAParser.DEVICE.MODEL, [UAParser.DEVICE.TYPE, UAParser.DEVICE.TABLET]],\n        [/(myphone)/i], [UAParser.DEVICE.VENDOR, [UAParser.DEVICE.TYPE, UAParser.DEVICE.MOBILE]]\n    ];\n    let myParser2 = new UAParser({\n        browser: myOwnListOfBrowsers,\n        device: myOwnListOfDevices\n    });\n    let myUA2 = 'Mozilla/5.0 MyTab 14 Pro Max';\n    assert.deepEqual(myParser2.setUA(myUA2).getDevice(), {vendor: \"MyTab\", model: \"14 Pro Max\", type: \"tablet\"});\n\n    let myParser3 = new UAParser([{ \n        browser: myOwnListOfBrowsers \n    }, { \n        device: myOwnListOfDevices \n    }]);\n    assert.deepEqual(myParser3.setUA(myUA2).getDevice(), {vendor: \"MyTab\", model: \"14 Pro Max\", type: \"tablet\"});\n});\n\ndescribe('User-agent with trailing space', function () {\n    it ('trailing space will be trimmed', function () {\n        const uastring = '     Opera/9.21 (Windows NT 5.1; U; ru)     ';\n        const { ua } = UAParser(uastring);\n        assert.equal(ua, 'Opera/9.21 (Windows NT 5.1; U; ru)     ');\n    });\n});\n\ndescribe('User-agent length', function () {\n    var UA_MAX_LENGTH = 500;\n\n    // Real data from https://stackoverflow.com/questions/654921/how-big-can-a-user-agent-string-get#answer-6595973\n    var uaString = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; 66760635803; runtime 11.00294; 876906799603; 97880703; 669602703; 9778063903; 877905603; 89670803; 96690803; 8878091903; 7879040603; 999608065603; 799808803; 6666059903; 669602102803; 888809342903; 696901603; 788907703; 887806555703; 97690214703; 66760903; 968909903; 796802422703; 8868026703; 889803611803; 898706903; 977806408603; 976900799903; 9897086903; 88780803; 798802301603; 9966008603; 66760703; 97890452603; 9789064803; 96990759803; 99960107703; 8868087903; 889801155603; 78890703; 8898070603; 89970603; 89970539603; 89970488703; 8789007603; 87890903; 877904603; 9887077703; 798804903; 97890264603; 967901703; 87890703; 97690420803; 79980706603; 9867086703; 996602846703; 87690803; 6989010903; 977809603; 666601903; 876905337803; 89670603; 89970200903; 786903603; 696901911703; 788905703; 896709803; 96890703; 998601903; 88980703; 666604769703; 978806603; 7988020803; 996608803; 788903297903; 98770043603; 899708803; 66960371603; 9669088903; 69990703; 99660519903; 97780603; 888801803; 9867071703; 79780803; 9779087603; 899708603; 66960456803; 898706824603; 78890299903; 99660703; 9768079803; 977901591603; 89670605603; 787903608603; 998607934903; 799808573903; 878909603; 979808146703; 9996088603; 797803154903; 69790603; 99660565603; 7869028603; 896707703; 97980965603; 976907191703; 88680703; 888809803; 69690903; 889805523703; 899707703; 997605035603; 89970029803; 9699094903; 877906803; 899707002703; 786905857603; 69890803; 97980051903; 997603978803; 9897097903; 66960141703; 7968077603; 977804603; 88980603; 989700803; 999607887803; 78690772803; 96990560903; 98970961603; 9996032903; 9699098703; 69890655603; 978903803; 698905066803; 977806903; 9789061703; 967903747703; 976900550903; 88980934703; 8878075803; 8977028703; 97980903; 9769006603; 786900803; 98770682703; 78790903; 878906967903; 87690399603; 99860976703; 796805703; 87990603; 968906803; 967904724603; 999606603; 988705903; 989702842603; 96790603; 99760703; 88980166703; 9799038903; 98670903; 697905248603; 7968043603; 66860703; 66860127903; 9779048903; 89670123903; 78890397703; 97890603; 87890803; 8789030603; 69990603; 88880763703; 9769000603; 96990203903; 978900405903; 7869022803; 699905422903; 97890703; 87990903; 878908703; 7998093903; 898702507603; 97780637603; 966907903; 896702603; 9769004803; 7869007903; 99660158803; 7899099603; 8977055803; 99660603; 7889080903; 66660981603; 997604603; 6969089803; 899701903; 9769072703; 666603903; 99860803; 997608803; 69790903; 88680756703; 979805677903; 9986047703; 89970803; 66660603; 96690903; 8997051603; 789901209803; 8977098903; 968900326803; 87790703; 98770024803; 697901794603; 69990803; 887805925803; 968908903; 97880603; 897709148703; 877909476903; 66760197703; 977908603; 698902703; 988706504803; 977802026603; 88680964703; 8878068703; 987705107903; 978902878703; 8898069803; 9768031703; 79680803; 79980803; 669609328703; 89870238703; 99960593903; 969904218703; 78890603; 9788000703; 69690630903; 889800982903; 988709748803; 7968052803; 99960007803; 969900800803; 668604817603; 66960903; 78790734603; 8868007703; 79780034903; 8878085903; 976907603; 89670830803; 877900903; 969904889703; 7978033903; 8987043903; 99860703; 979805903; 667603803; 976805348603; 999604127603; 97790701603; 78990342903; 98770672903; 87990253903; 9877027703; 97790803; 877901895603; 8789076903; 896708595603; 997601903; 799806903; 97690603; 87790371703; 667605603; 99760303703; 97680283803; 788902750803; 787909803; 79780603; 79880866903; 9986050903; 87890543903; 979800803; 97690179703; 876901603; 699909903; 96990192603; 878904903; 877904734903; 796801446903; 977904803; 9887044803; 797805565603; 98870789703; 7869093903; 87790727703; 797801232803; 666604803; 9778071903; 9799086703; 6969000903; 89670903; 8799075903; 897708903; 88680903; 97980362603; 97980503903; 889803256703; 88980388703; 789909376803; 69690703; 6969025903; 89970309903; 96690703; 877901847803; 968901903; 96690603; 88680607603; 7889001703; 789904761803; 976807703; 976902903; 878907889703; 9897014903; 896707046603; 696909903; 666603998903; 969902703; 79680421803; 9769075603; 798800192703; 97990903; 9689024903; 668604803; 969908671903; 9996094703; 69990642703; 97890895903; 977805619903; 79980859903; 88980443803; 98970649603; 997602703; 888802169903; 699907803; 667602028803; 786903283903; 997607703; 969909803; 798809925903; 9976045603; 97790903; 9789001903; 966903603; 9789069603; 968906603; 6989091803; 896701603; 6979059803; 978803903; 997606362603; 88980803; 98970803; 88880921703; 8997065703; 899700703; 698908703; 797801027903; 7889050903; 87890603; 78690703; 99660069703; 97980309903; 976800603; 666606803; 898707703; 79880019803; 66960250803; 7978049803; 88780602603; 79680903; 88880792703; 96990903; 667608603; 87790730903; 98970903; 9699032903; 8987004803; 88880703; 89770046603; 978800803; 969908903; 9798022603; 696901903; 799803703; 989703703; 668605903; 79780903; 998601371703; 796803339703; 87890922603; 898708903; 9966061903; 66960891903; 96790903; 8779050803; 98870858803; 976909298603; 9887029903; 669608703; 979806903; 878903803; 99960703; 9789086703; 979801803; 66960008703; 979806830803; 99760212703; 786906603; 797807603; 789907297703; 96990703; 786901603; 796807766603; 896702651603; 789902585603; 66660925903; 9986085703; 66960302703; 69890703; 789900703; 89970903; 9679060703; 9789002903; 979908821603; 986708140803; 976809828703; 7988082803; 79680997903; 99960803; 9788081903; 979805703; 787908603; 66960602803; 9887098703; 978803237703; 888806804603; 999604703; 977904703; 966904635703; 97680291703; 977809345603; 8878046703; 988709803; 976900773603; 989703903; 88780198603; 87790603; 986708703; 78890604703; 87790544803; 976809850903; 887806703; 987707527603; 79880803; 9897059603; 897709820603; 97880804803; 66960026703; 9789062803; 9867090803; 669600603; 8967087703; 78890903; 89770903; 97980703; 976802687603; 66860400803; 979901288603; 96990160903; 99860228903; 966900703; 66760603; 9689035703; 9779064703; 7968023603; 87890791903; 98770870603; 9798005803; 6969087903; 9779097903; 6979065703; 699903252603; 79780989703; 87690901803; 978905763903; 977809703; 97790369703; 899703269603; 8878012703; 78790803; 87690395603; 8888042803; 667607689903; 8977041803; 6666085603; 6999080703; 69990797803; 88680721603; 99660519803; 889807603; 87890146703; 699906325903; 89770603; 669608615903; 9779028803; 88880603; 97790703; 79780703; 97680355603; 6696024803; 78790784703; 97880329903; 9699077703; 89870803; 79680227903; 976905852703; 8997098903; 896704796703; 66860598803; 9897036703; 66960703; 9699094703; 9699008703; 97780485903; 999603179903; 89770834803; 96790445603; 79680460903; 9867009603; 89870328703; 799801035803; 989702903; 66960758903; 66860150803; 6686088603; 9877092803; 96990603; 99860603; 987703663603; 98870903; 699903325603; 87790803; 97680703; 8868030703; 9799030803; 89870703; 97680803; 9669054803; 6979097603; 987708046603; 999608603; 878904803; 998607408903; 968903903; 696900703; 977907491703; 6686033803; 669601803; 99960290603; 887809169903; 979803703; 69890903; 699901447903; 8987064903; 799800603; 98770903; 8997068703; 967903603; 66760146803; 978805087903; 697908138603; 799801603; 88780964903; 989708339903; 8967048603; 88880981603; 789909703; 796806603; 977905977603; 989700603; 97780703; 9669062603; 88980714603; 897709545903; 988701916703; 667604694903; 786905664603; 877900803; 886805490903; 89970559903; 99960531803; 7998033903; 98770803; 78890418703; 669600872803; 996605216603; 78690962703; 667604903; 996600903; 999608903; 9699083803; 787901803; 97780707603; 787905312703; 977805803; 8977033703; 97890708703; 989705521903; 978800703; 698905703; 78890376903; 878907703; 999602903; 986705903; 668602719603; 979901803; 997606903; 66760393903; 987703603; 78790338903; 96890803; 97680596803; 666601603; 977902178803; 877902803; 78790038603; 8868075703; 99960060603)';\n\n    it('greater than ' + UA_MAX_LENGTH + ' should be trimmed down', function () {\n        assert.strictEqual(UAParser(uaString).ua.length, UA_MAX_LENGTH);\n    });\n});\n\ndescribe('Using Require.js', function () {\n    it('should loaded automatically', function(done) {\n        requirejs.config({\n            baseUrl : 'dist',\n            paths   : {\n                'ua-parser-js' : 'ua-parser.min'\n            }\n        });\n        requirejs(['ua-parser-js'], function(ua) {\n            var parser = new ua('Dillo/1.0');\n            assert.deepStrictEqual(parser.getBrowser().name, 'Dillo');\n            done();\n        });\n    });\n});\n\ndescribe('Testing regexes', function () {\n\n    var regexes;\n\n    before('Read main js file', function () {\n        var code = fs.readFileSync('src/main/ua-parser.js', 'utf8').toString();\n        var ast = parseJS(code, { sourceType: \"script\" });\n        regexes = [];\n        traverse(ast, {\n            RegExpLiteral: (path) => {\n                regexes.push(path.node.pattern);\n            }\n        });\n\n        if (regexes.length === 0) {\n            throw new Error(\"Regexes cannot be empty!\");\n        }\n    });\n\n    describe('Begin testing', function () {\n        it('all regexes in main file', function () {\n            describe('Test against `safe-regex` module', function () {\n                regexes.forEach(function (regex) {\n                    it(`Should pass \\`safe-regex\\`: ${regex}`, function () {\n                        assert.strictEqual(safe(regex), true);\n                    });\n                });\n            });\n        });\n    });\n});\n\n\ndescribe('is() utility method', function () {\n    let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');\n\n    it('Should match full name', function () {\n        assert.strictEqual(uap.getBrowser().name, \"IEMobile\");\n        assert.strictEqual(uap.getBrowser().is(\"IEMobile\"), true);\n        assert.strictEqual(uap.getBrowser().is(\"IE\"), false);\n        assert.strictEqual(uap.getBrowser().is(\"11.0\"), false);\n    });\n\n    it('Should ignore \"Browser\" suffix', function () {\n        assert.strictEqual(uap.getBrowser().is(\"IEMobile Browser\"), true);\n    });\n\n    it('Should ignore case', function () {\n        assert.strictEqual(uap.getEngine().name, \"Trident\");\n        assert.strictEqual(uap.getEngine().is(\"tRiDeNt\"), true);\n        assert.strictEqual(uap.getEngine().is(\"7.0\"), false);\n    });\n\n    it('Should get exact name', function () {\n        assert.strictEqual(uap.getOS().name, \"Windows Phone\");\n        assert.strictEqual(uap.getOS().is(\"Windows Phone\"), true);\n        assert.strictEqual(uap.getOS().is(\"Windows Phone OS\"), true);\n        assert.strictEqual(uap.getOS().is(\"Windows Mobile\"), false);\n        assert.strictEqual(uap.getOS().is(\"Android\"), false);\n    });\n\n    it('Should check all device properties', function () {\n        assert.deepEqual(uap.getDevice(), {\n            vendor : \"Nokia\", \n            model : \"Lumia 635\", \n            type : \"mobile\"\n        });\n        assert.strictEqual(uap.getDevice().is(\"Nokia\"), true);\n        assert.strictEqual(uap.getDevice().is(\"Lumia 635\"), true);\n        assert.strictEqual(uap.getDevice().is(\"mobile\"), true);\n\n        assert.strictEqual(uap.getResult().device.is(\"Nokia\"), true);\n    });\n\n    it('Should get result after reassignment', function () {\n        uap.setUA(\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36\");\n        assert.strictEqual(uap.getOS().name, \"macOS\");\n        assert.strictEqual(uap.getOS().is(\"Mac OS\"), true);\n        assert.strictEqual(uap.getOS().is(\"macOS\"), true);\n        assert.strictEqual(uap.getOS().is(\"mac OS\"), true);\n        \n        assert.strictEqual(uap.getOS().is(\"M ac\"), false);\n        assert.strictEqual(uap.getOS().is(\"M      a c   \"), false);\n        assert.strictEqual(uap.getOS().is(\"Mac OS OS\"), false);\n        assert.strictEqual(uap.getOS().is(\"Mac OS X\"), false);\n\n        assert.strictEqual(uap.getBrowser().is(\"Chrome\"), true);\n        assert.strictEqual(uap.getEngine().is(\"Blink\"), true);\n    });\n\n    it('Should refrain from \"undefined\" until all properties are checked', function () {\n        assert.strictEqual(uap.getDevice().is(\"undefined\"), false);\n        assert.strictEqual(uap.getDevice().is(\"Apple\"), true);\n\n        uap.setUA(\"\");\n        assert.strictEqual(uap.getDevice().model, undefined);\n        assert.strictEqual(uap.getDevice().is(\"undefined\"), false);\n        assert.strictEqual(uap.getDevice().is(undefined), true);\n    });\n\n    //it('Should accept arch equivalent name', function () {\n    it('Should accept exact arch name', function () {\n        uap.setUA(\"Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0\");\n        assert.strictEqual(uap.getCPU().architecture, \"ia32\");\n        assert.strictEqual(uap.getCPU().is(\"ia32\"), true);\n        assert.strictEqual(uap.getCPU().is(\"x86\"), false);\n\n        uap.setUA(\"Opera/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto/2.2.15 Version/10.10\");\n        assert.strictEqual(uap.getCPU().architecture, \"amd64\");\n        assert.strictEqual(uap.getCPU().is(\"amd64\"), true);\n        assert.strictEqual(uap.getCPU().is(\"x86-64\"), false);\n        assert.strictEqual(uap.getCPU().is(\"x64\"), false);\n    });\n});\n\ndescribe('toString() utility method', function () {\n    it('Should return full name', function () {\n        let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');\n        assert.strictEqual(uap.getBrowser().name, \"IEMobile\");\n        assert.strictEqual(uap.getBrowser().version, \"11.0\");\n        assert.strictEqual(uap.getBrowser().major, \"11\");\n        assert.strictEqual(uap.getBrowser().toString(), \"IEMobile 11.0\");\n\n        assert.strictEqual(uap.getCPU().architecture, \"arm\");\n        assert.strictEqual(uap.getCPU().toString(), \"arm\");\n\n        assert.strictEqual(uap.getDevice().vendor, \"Nokia\");\n        assert.strictEqual(uap.getDevice().model, \"Lumia 635\");\n        assert.strictEqual(uap.getDevice().type, \"mobile\");\n        assert.strictEqual(uap.getDevice().toString(), \"Nokia Lumia 635\");\n\n        assert.strictEqual(uap.getEngine().name, \"Trident\");\n        assert.strictEqual(uap.getEngine().version, \"7.0\");\n        assert.strictEqual(uap.getEngine().toString(), \"Trident 7.0\");\n\n        assert.strictEqual(uap.getOS().name, \"Windows Phone\");\n        assert.strictEqual(uap.getOS().version, \"8.1\");\n        assert.strictEqual(uap.getOS().toString(), \"Windows Phone 8.1\");\n    });\n});\n\ndescribe('Read user-agent data from req.headers', function () {\n    const ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)';\n    const ext = {\n        engine : [\n            [/(msie)/i], [[UAParser.ENGINE.NAME, 'Custom Browser 1']],\n            [/(edge)/i], [[UAParser.ENGINE.NAME, 'Custom Browser 2']]\n        ]\n    };\n    const req = { \n        headers : {\n            'user-agent' : 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0'\n        }\n    };\n\n    it('Can be called with UAParser(ua)', function () {    \n        let engine = UAParser(ua).engine;\n        assert.strictEqual(engine.name, \"Trident\");\n    });\n\n    it('Can be called with UAParser(ua, extensions)', function () {    \n        let engine = UAParser(ua, ext).engine;\n        assert.strictEqual(engine.name, \"Custom Browser 1\");\n    });\n\n    it('Can be called with UAParser(ua, extensions, headers)', function () {    \n        let engine = UAParser(ua, ext, req.headers).engine;\n        assert.strictEqual(engine.name, \"Custom Browser 1\");\n    });\n\n    it('Can be called with UAParser(ua, headers)', function () {    \n        let engine = UAParser(ua, req.headers).engine;\n        assert.strictEqual(engine.name, \"Trident\");\n    });\n\n    it('Can be called with UAParser(extensions, headers)', function () {    \n        let engine = UAParser(ext, req.headers).engine;\n        assert.strictEqual(engine.name, \"Custom Browser 2\");\n    });\n\n    it('Can be called with UAParser(headers)', function () {    \n        let engine = UAParser(req.headers).engine;\n        assert.strictEqual(engine.name, \"EdgeHTML\");\n    });\n\n    // Headers supported in node 18+ - https://developer.mozilla.org/en-US/docs/Web/API/Headers\n    if (typeof Headers !== 'undefined') {\n        it('Fetch API\\'s Header can be passed directly into headers', () => {\n            const reqHeaders = new Headers();\n            reqHeaders.append('User-Agent', 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+');\n            const { browser } = UAParser(reqHeaders);\n            assert.strictEqual(browser.is('Midori'), true);\n        });\n    }\n\n    it('Headers field name should be case insensitive', function () {    \n        const hEaDeRs = {\n            'uSeR-aGenT' : 'Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+'\n        };\n        const { browser } = UAParser(hEaDeRs);\n        assert.strictEqual(browser.toString(), \"Midori 0.2.2\");\n    });\n\n    it('Empty headers should not raise any error', function () {    \n        const emptyHeaders = {};\n        const { browser } = UAParser(emptyHeaders);\n        assert.strictEqual(browser.toString(), \"undefined\");\n    });\n});\n"
  },
  {
    "path": "test/unit/submodules/bot-detection.spec.js",
    "content": "const assert = require('assert');\nconst { UAParser } = require('../../../src/main/ua-parser');\nconst { isAICrawler, isBot } = require('../../../src/bot-detection/bot-detection');\nconst { Bots, Emails } = require('../../../src/extensions/ua-parser-extensions');\n\ndescribe('isAICrawler()', () => {\n    it('Can detect AI Crawlers', () => {\n        \n        // AI Crawlers\n        const claudeBot = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)';\n        const searchGPT = 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot';\n        const semrushAI = 'Mozilla/5.0 (compatible; SemrushBot-OCOB/1; +https://www.semrush.com/bot/)';\n\n        // Using string as param\n        assert.equal(isAICrawler(claudeBot), true);\n        assert.equal(isAICrawler(searchGPT), true);\n        assert.equal(isAICrawler(semrushAI), true);\n\n        // Using IResult as param\n        const botParser = new UAParser(Bots);\n        const result = botParser.setUA(semrushAI).getResult();\n        assert.equal(isAICrawler(result), true);\n\n        // Non-AI Crawlers\n        const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';\n\n        assert.equal(isAICrawler(firefox), false);\n    });\n});\n\ndescribe('isBot()', () => {\n    it('Can detect general Bots', () => {\n        \n        // Bots\n        const ahrefsBot = 'Mozilla/5.0 (compatible; AhrefsBot/7.0; +http://ahrefs.com/robot/)';\n        const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';\n\n        assert.equal(isBot(ahrefsBot), true);\n        assert.equal(isBot(scrapy), true);\n\n        // Non-bots\n        const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';\n        const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';\n\n        assert.equal(isBot(firefox), false);\n        assert.equal(isBot(thunderbird), false);\n    });\n});"
  },
  {
    "path": "test/unit/submodules/browser-detection.spec.js",
    "content": "const assert = require('assert');\nconst { UAParser } = require('../../../src/main/ua-parser');\nconst { isChromeFamily } = require('../../../src/browser-detection/browser-detection');\n\ndescribe('isChromeFamily()', () => {\n    it('Can detect Chromium-based browser', () => {\n        \n        const edge = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.2151.58';\n        const firefox = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';\n\n        assert.equal(isChromeFamily(UAParser(edge)), true);\n        assert.equal(isChromeFamily(edge), true);\n        assert.equal(isChromeFamily(UAParser(firefox)), false);\n        assert.equal(isChromeFamily(firefox), false);\n    });\n});"
  },
  {
    "path": "test/unit/submodules/device-detection.spec.js",
    "content": "const assert = require('assert');\nconst { UAParser } = require('../../../src/main/ua-parser');\nconst { getDeviceVendor, isAppleSilicon } = require('../../../src/device-detection/device-detection');\nconst { DeviceVendor } = require('../../../src/enums/ua-parser-enums');\n\ndescribe('getDeviceVendor()', () => {\n    it('Can guess the device vendor from a model name', () => {\n        \n        const sm = 'SM-A605G';\n        const redmi = 'Redmi Note 8';\n        const nexus = 'Nexus 6P';\n        const aquos = 'AQUOS-TVX19B';\n\n        assert.equal(getDeviceVendor(sm), DeviceVendor.SAMSUNG);\n        assert.equal(getDeviceVendor(redmi), DeviceVendor.XIAOMI);\n        assert.equal(getDeviceVendor(nexus), DeviceVendor.HUAWEI);\n        assert.equal(getDeviceVendor(aquos), DeviceVendor.SHARP);\n    });\n});\n\ndescribe('isAppleSilicon()', () => {\n    it('Can detect Apple Silicon device', () => {\n        \n        const macARM = 'Mozilla/5.0 (Macintosh; ARM; Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';\n        const macIntel = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0';\n\n        assert.equal(isAppleSilicon(UAParser(macIntel)), false);\n        assert.equal(isAppleSilicon(macIntel), false);\n        assert.equal(isAppleSilicon(UAParser(macARM)), true);\n        assert.equal(isAppleSilicon(macARM), true);\n    });\n});"
  },
  {
    "path": "test/unit/submodules/extensions.spec.js",
    "content": "const fs = require('fs');\nconst assert = require('assert');\nconst parseJS = require('@babel/parser').parse;\nconst traverse = require('@babel/traverse').default;\nconst safe = require('safe-regex');\nconst { UAParser } = require('../../../src/main/ua-parser');\nconst { Bots, CLIs, Crawlers, Emails, Fetchers, InApps, Libraries, Vehicles } = require('../../../src/extensions/ua-parser-extensions');\nconst { BrowserType, OSName, Extension } = require('../../../src/enums/ua-parser-enums');\nconst { CLI, Crawler, Email, Fetcher, Library } = Extension.BrowserName;\n\ndescribe('Extensions', () => {\n    [   \n        ['CLIs', 'cli', CLIs], \n        ['Crawlers', 'crawler', Crawlers], \n        ['Emails', 'email', Emails], \n        ['Fetchers', 'fetcher', Fetchers],\n        ['InApps', 'inapp', InApps],\n        ['Libraries', 'library', Libraries],\n        ['Vehicles', 'vehicle', Vehicles]\n    ]\n    .forEach(([desc, path, ext]) => {\n        const tests = require(`../../data/ua/extension/${path}.json`);\n        describe(desc, () => {\n            tests.forEach((test) => {\n                it(`Can detect ${test.desc}: \"${test.ua}\"`, () => {\n                    const { browser, device } = UAParser(test.ua, ext);\n                    if ('browser' in ext) {\n                        assert.strictEqual(String(browser.name), test.expect.name);\n                        assert.strictEqual(String(browser.version), test.expect.version);\n                        assert.strictEqual(String(browser.type), test.expect.type);\n                    } else if ('device' in ext) {\n                        assert.strictEqual(String(device.vendor), test.expect.vendor);\n                        assert.strictEqual(String(device.model), test.expect.model);\n                        assert.strictEqual(String(device.type), test.expect.type);\n                    }\n                });\n            });\n        });\n    });\n\n    // Existing test cases\n    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)';\n    const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';\n    const axios = 'axios/1.3.5';\n    const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3';\n    const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';\n\n    // New test cases for updated Regex logic\n    const macOutlook = 'MacOutlook/16.61.22041701 (Intel Mac OS X 10.15.7)';\n    const yahooMobile = 'YahooMobile/1.0 (mail; 3.0.5.1311380)';\n\n    assert.equal(UAParser(scrapy, Bots).browser.name, Library.SCRAPY);\n\n    const emailParser = new UAParser(Emails);\n    \n    // Verify Standard Outlook\n    assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK, version: \"16.0.9126\", major: \"16\", type: BrowserType.EMAIL});\n    \n    // Verify Thunderbird\n    assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: Email.THUNDERBIRD, version: \"78.13.0\", major: \"78\", type: BrowserType.EMAIL});\n\n    // Verify New MacOutlook Logic (Distinguishing it from Windows Outlook)\n    assert.deepEqual(emailParser.setUA(macOutlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK_MAC, version: \"16.61.22041701\", major: \"16\", type: BrowserType.EMAIL});\n\n    // Verify Yahoo Mobile Logic (Tightened Regex)\n    // Note: We expect 'Yahoo Mail' (Email.YAHOO_MAIL) because of the normalization helper.\n    assert.deepEqual(emailParser.setUA(yahooMobile).getBrowser(), {name: Email.YAHOO_MAIL, version: \"1.0\", major: \"1\", type: BrowserType.EMAIL});\n\n    const libraryParser = new UAParser(Libraries);\n    assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: Library.AXIOS, version: \"1.3.5\", major: \"1\", type: BrowserType.LIBRARY});\n    assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: Library.JSDOM, version: \"20.0.3\", major: \"20\", type: BrowserType.LIBRARY});\n    assert.deepEqual(libraryParser.setUA(scrapy).getBrowser(), {name: Library.SCRAPY, version: \"1.5.0\", major: \"1\", type: BrowserType.LIBRARY});\n\n    // Bluesky\n    const bluesky = 'Mozilla/5.0 (compatible; Bluesky Cardyb/1.1; +mailto:support@bsky.app)';\n    assert.deepEqual(new UAParser(bluesky, Bots).getBrowser(), {\n        name: Fetcher.BLUESKY,\n        version: '1.1',\n        major: '1',\n        type: BrowserType.FETCHER\n    });\n\n    const whatsapp = \"WhatsApp/2.0 A\";\n    assert.deepEqual(new UAParser(whatsapp, Fetchers).getOS(), {\n        name : OSName.ANDROID,\n        version : undefined\n    });\n});\n\ndescribe('Merge', () => {\n    it('Can merge multiple extensions', () => {\n        const wget = 'Wget/1.21.1';\n        const facebookBot = 'Mozilla/5.0 (compatible; FacebookBot/1.0; +https://developers.facebook.com/docs/sharing/webmasters/facebookbot/)';\n\n        // try merging crawlers & CLIs\n        const crawlersAndCLIs = { browser : [...Crawlers.browser, ...CLIs.browser]};\n        const crawlersAndCLIsParser = new UAParser(crawlersAndCLIs);\n        assert.deepEqual(crawlersAndCLIsParser.setUA(wget).getBrowser(), {name: CLI.WGET, version: \"1.21.1\", major: \"1\", type: BrowserType.CLI});\n        assert.deepEqual(crawlersAndCLIsParser.setUA(facebookBot).getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: \"1.0\", major: \"1\", type: BrowserType.CRAWLER});\n\n        // alternative merge options\n        const crawlersAndCLIsParser2 = new UAParser([Crawlers, CLIs]);\n        const crawlersAndCLIsParser3 = new UAParser(facebookBot, [Crawlers, CLIs]);\n        assert.deepEqual(crawlersAndCLIsParser2.setUA(wget).getBrowser(), {name: CLI.WGET, version: \"1.21.1\", major: \"1\", type: BrowserType.CLI});\n        assert.deepEqual(crawlersAndCLIsParser3.getBrowser(), {name: Crawler.META_FACEBOOKBOT, version: \"1.0\", major: \"1\", type: BrowserType.CRAWLER});\n    });\n});\n\ndescribe('Testing the safety of regexes', () => {\n\n    let regexes;\n    let code = fs.readFileSync('src/extensions/ua-parser-extensions.js', 'utf8').toString();\n    let ast = parseJS(code, { sourceType: 'script' });\n    regexes = [];\n    traverse(ast, {\n        RegExpLiteral: (path) => {\n            regexes.push(path.node.pattern);\n        }\n    });\n\n    if (regexes.length === 0) {\n        throw new Error('Regexes cannot be empty!');\n    }\n\n    describe('Checking for potentially vulnerable regex', () => {\n        for (let regex of regexes) {\n            it('Test against `safe-regex` : ' + regex, () => {\n                assert.strictEqual(safe(regex), true);\n            });\n        }\n    });\n});"
  },
  {
    "path": "test/unit/submodules/helpers.spec.js",
    "content": "const assert = require('assert');\nconst { isFrozenUA, getOutlookEdition } = require('../../../src/helpers/ua-parser-helpers');\n\ndescribe('isFrozenUA()', () => {\n    it('matches supplied user-agent string with known frozen user-agent pattern', () => {\n    \n        const regularMobileUA = \"Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Mobile Safari/537.36\";\n        const frozenMobileUA = \"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36\";\n\n        assert.equal(isFrozenUA(regularMobileUA), false);\n        assert.equal(isFrozenUA(frozenMobileUA), true);\n    });\n});\n\ndescribe('getOutlookEdition()', () => {\n    it('identifies Windows versions correctly', () => {\n        // MSI Version (Older engine)\n        assert.equal(getOutlookEdition('Microsoft Outlook', '16.0.4266.1001'), 'Outlook 2016 (MSI / Volume License)');\n        // Click-to-Run (Modern engine)\n        assert.equal(getOutlookEdition('Microsoft Outlook', '16.0.14326.20000'), 'Outlook 365 / 2019+ (Modern)');\n        // Legacy Major Version\n        assert.equal(getOutlookEdition('Microsoft Outlook', '15.0.4569.1506'), 'Outlook 2013');\n    });\n\n    it('identifies Mac versions correctly', () => {\n        assert.equal(getOutlookEdition('MacOutlook', '16.61'), 'Outlook for Mac (Modern)');\n        assert.equal(getOutlookEdition('MacOutlook', '15.4'), 'Outlook for Mac (Legacy)');\n    });\n\n    it('returns original name for unknown inputs', () => {\n        assert.equal(getOutlookEdition('Thunderbird', '91.0'), 'Thunderbird');\n    });\n\n    it('handles New Outlook (OneOutlook) correctly', () => {\n        // New Outlook usually sends a browser UA, but if it sends \"Outlook\" without version info matches,\n        // it shouldn't trigger the Legacy/MSI logic.\n        assert.equal(getOutlookEdition('Microsoft Outlook', 'SomeRandomString'), 'Microsoft Outlook');\n    });\n});"
  },
  {
    "path": "test/unit/ua-ch.js",
    "content": "const assert = require('assert');\nconst { UAParser } = require('../../src/main/ua-parser');\nconst { BrowserName, CPUArch, DeviceType, DeviceVendor, EngineName, OSName } = require('../../src/enums/ua-parser-enums');\nconst UACHTests = require('../data/ua-ch/headers');\n\ndescribe('Map UA-CH headers', () => {\n\n    const headers = {\n        'sec-ch-ua' : '\"Chromium\";v=\"93\", \"Google Chrome\";v=\"93\", \" Not;A Brand\";v=\"99\"',\n        'sec-ch-ua-full-version-list' : '\"Chromium\";v=\"93.0.1.2\", \"Google Chrome\";v=\"93.0.1.2\", \" Not;A Brand\";v=\"99.0.1.2\"',\n        'sec-ch-ua-arch' : '\"arm\"',\n        'sec-ch-ua-bitness' : '\"64\"',\n        'sec-ch-ua-mobile' : '?1',\n        'sec-ch-ua-model' : '\"Pixel 99\"',\n        'sec-ch-ua-platform' : '\"Windows\"',\n        'sec-ch-ua-platform-version' : '\"13\"',\n        'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'\n    };\n    \n    let uap = UAParser(headers).withClientHints();\n    let browser = new UAParser(headers).getBrowser().withClientHints();\n    let cpu = new UAParser(headers).getCPU().withClientHints();\n    let device = new UAParser(headers).getDevice().withClientHints();\n    let engine = new UAParser(headers).getEngine().withClientHints();\n    let os = new UAParser(headers).getOS().withClientHints();\n\n    it('Can read from client-hints headers using `withClientHints()`', () => {  \n\n        assert.strictEqual(uap.ua, \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\");\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, \"93.0.1.2\");\n        assert.strictEqual(uap.browser.major, \"93\");        \n        assert.strictEqual(browser.name, BrowserName.CHROME);\n        assert.strictEqual(browser.version, \"93.0.1.2\");\n        assert.strictEqual(browser.major, \"93\");\n        assert.strictEqual(uap.cpu.architecture, CPUArch.ARM_64);\n        assert.strictEqual(cpu.architecture, CPUArch.ARM_64);\n        assert.strictEqual(uap.device.type, DeviceType.MOBILE);\n        assert.strictEqual(uap.device.model, \"Pixel 99\");\n        assert.strictEqual(uap.device.vendor, DeviceVendor.GOOGLE);\n        assert.strictEqual(device.type, DeviceType.MOBILE);\n        assert.strictEqual(device.model, \"Pixel 99\");\n        assert.strictEqual(device.vendor, DeviceVendor.GOOGLE);\n        assert.strictEqual(uap.engine.name, EngineName.BLINK);\n        assert.strictEqual(uap.engine.version, '93.0.1.2');\n        assert.strictEqual(engine.name, EngineName.BLINK);\n        assert.strictEqual(engine.version, '93.0.1.2');\n        assert.strictEqual(uap.os.name, OSName.WINDOWS);\n        assert.strictEqual(uap.os.version, \"11\");\n        assert.strictEqual(os.name, OSName.WINDOWS);\n        assert.strictEqual(os.version, \"11\");\n    });\n\n    it('Only read from user-agent header when called without `withClientHints()`', () => { \n\n        uap = UAParser(headers);\n        browser = new UAParser(headers).getBrowser();\n        cpu = new UAParser(headers).getCPU();\n        device = new UAParser(headers).getDevice();\n        engine = new UAParser(headers).getEngine();\n        os = new UAParser(headers).getOS();\n\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, \"110.0.0.0\");\n        assert.strictEqual(uap.browser.major, \"110\");\n        assert.strictEqual(uap.cpu.architecture, CPUArch.X86_64);\n        assert.strictEqual(uap.device.type, undefined);\n        assert.strictEqual(uap.device.model, undefined);\n        assert.strictEqual(uap.device.vendor, undefined);\n        assert.strictEqual(uap.engine.name, EngineName.BLINK);\n        assert.strictEqual(uap.engine.version, '110.0.0.0');\n        assert.strictEqual(uap.os.name, OSName.LINUX);\n        assert.strictEqual(uap.os.version, undefined);\n    });\n\n    it('Fallback to user-agent header when using `withClientHints()` but found no client hints-related headers',  () => {  \n\n        const headers2 = {\n            'sec-ch-ua-mobile' : '?1',\n            'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'\n        };\n        \n        uap = UAParser(headers2).withClientHints();\n\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, \"110.0.0.0\");\n        assert.strictEqual(uap.browser.major, \"110\");\n        assert.strictEqual(uap.cpu.architecture, CPUArch.X86_64);\n        assert.strictEqual(uap.device.type, DeviceType.MOBILE);\n        assert.strictEqual(uap.device.model, undefined);\n        assert.strictEqual(uap.device.vendor, undefined);\n        assert.strictEqual(uap.engine.name, EngineName.BLINK);\n        assert.strictEqual(uap.engine.version, '110.0.0.0');\n        assert.strictEqual(uap.os.name, OSName.LINUX);\n        assert.strictEqual(uap.os.version, undefined);\n    });\n\n    it('Can detect Apple silicon from client hints data', () => {  \n\n        // https://github.com/faisalman/ua-parser-js/issues/489#issuecomment-1479213579\n        const httpHeadersFromAppleSilicon = {\n            'sec-ch-ua-arch' : 'arm',\n            'sec-ch-ua-platform' : 'macOS',\n            'sec-ch-ua-mobile' : '?0',\n            'sec-ch-ua' : '\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"',\n            'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0'\n        };\n        \n        UAParser(httpHeadersFromAppleSilicon).withClientHints().then(ua => {\n\n            // Only works in Chrome\n            /* \n                if (ua.os.is(\"macOS\") && \n                    ua.cpu.is(\"arm\") &&\n                    !ua.device.is(\"mobile\") && \n                    !ua.device.is(\"tablet\")) {\n                        // possibly an Apple silicon device\n                    }\n            */\n\n            assert.strictEqual(ua.os.is(OSName.MACOS), true);\n            assert.strictEqual(ua.cpu.is(CPUArch.ARM), true);            \n            assert.strictEqual(ua.device.is(DeviceType.MOBILE), false);\n            assert.strictEqual(ua.device.is(DeviceType.TABLET), false);\n        });\n    });\n\n    it('Can detect form-factors from client-hints', () => {  \n\n        const FFVR = {\n            'sec-ch-ua-form-factors' : '\"VR\"'\n        };\n\n        const FFEInk = {\n            'sec-ch-ua-form-factors' : '\"Tablet\", \"EInk\"'\n        };\n\n        const FFUnknown = {\n            'sec-ch-ua-form-factors' : '\"Unknown\"'\n        };\n        \n        UAParser(FFVR).withClientHints().then(ua => {\n            assert.strictEqual(ua.device.type, DeviceType.XR);\n        });\n\n        UAParser(FFEInk).withClientHints().then(ua => {\n            assert.strictEqual(ua.device.type, DeviceType.TABLET);\n        });\n\n\n        UAParser(FFUnknown).withClientHints().then(ua => {\n            assert.strictEqual(ua.device.type, undefined);\n        });\n    });\n\n    it('Avoid error on headers variation', () => {  \n\n        const headers2 = {\n            'sec-ch-ua' : '\"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"',\n            'sec-ch-ua-full-version-list' : '\"Google Chrome\", \"Chromium\", \"Not?A_Brand\";v=\"24.0.0.0\"',\n            'sec-ch-ua-full-version' : '\"\"',\n            'sec-ch-ua-mobile' : '?0',\n            'sec-ch-ua-arch' : '\"\"',\n            'sec-ch-ua-bitness' : '\"\"',\n            'sec-ch-ua-model' : '\"\"',\n            'sec-ch-ua-platform' : '\"Windows\"',\n            'sec-ch-ua-platform-version' : '\"\"',\n            'sec-ch-ua-wow64' : '?0',\n        };\n        \n        uap = UAParser(headers2).withClientHints();\n\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, undefined);\n        assert.strictEqual(uap.browser.major, undefined);\n    });\n\n    it('Prioritize more specific brand name regardless the order', () => {  \n\n        const headers3a = {\n            'sec-ch-ua-full-version-list' : '\"Not_A Brand;v=8, Chromium;v=120.0.6099.131, Google Chrome;v=120.0.6099.132\"'\n        };\n        const headers3b = {\n            'sec-ch-ua-full-version-list' : '\"Chromium;v=120.0.6099.131, Not_A Brand;v=8, Google Chrome;v=120.0.6099.132\"'\n        };\n        const headers3c = {\n            'sec-ch-ua-full-version-list' : '\"Google Chrome;v=120.0.6099.132, Chromium;v=120.0.6099.131, Not_A Brand;v=8\"'\n        };\n        const headers3d = {\n            'sec-ch-ua-full-version-list' : '\"Microsoft Edge;v=120.0.6099.133, Google Chrome;v=120.0.6099.132, Chromium;v=120.0.6099.131, Not_A Brand;v=8\"'\n        };\n        const headers3e = {\n            'sec-ch-ua-full-version-list' : '\"Chromium;v=120.0.6099.131, Google Chrome;v=120.0.6099.132, Microsoft Edge;v=120.0.6099.133, Not_A Brand;v=8\"'\n        };\n        const headers3f = {\n            'sec-ch-ua-full-version-list' : '\"Not_A Brand;v=8, Microsoft Edge;v=120.0.6099.133, Google Chrome;v=120.0.6099.132, Chromium;v=120.0.6099.131\"'\n        };\n        \n        uap = UAParser(headers3a).withClientHints();\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, \"120.0.6099.132\");\n\n        uap = UAParser(headers3b).withClientHints();\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, \"120.0.6099.132\");\n\n        uap = UAParser(headers3c).withClientHints();\n        assert.strictEqual(uap.browser.name, BrowserName.CHROME);\n        assert.strictEqual(uap.browser.version, \"120.0.6099.132\");\n\n        uap = UAParser(headers3d).withClientHints();\n        assert.strictEqual(uap.browser.name, BrowserName.EDGE);\n        assert.strictEqual(uap.browser.version, \"120.0.6099.133\");\n\n        uap = UAParser(headers3e).withClientHints();\n        assert.strictEqual(uap.browser.name, BrowserName.EDGE);\n        assert.strictEqual(uap.browser.version, \"120.0.6099.133\");\n\n        uap = UAParser(headers3f).withClientHints();\n        assert.strictEqual(uap.browser.name, BrowserName.EDGE);\n        assert.strictEqual(uap.browser.version, \"120.0.6099.133\");\n    });\n});\n\ndescribe('UA-CH Headers tests', () => {\n    UACHTests.forEach(test => {\n        it(`Test for ${test.desc}`, () => {\n            const { browser } = UAParser(test.headers).withClientHints();\n            assert.deepEqual(browser, test.expect.browser);\n        });\n    });\n});\n\ndescribe('Identify vendor & type of device from given model name', () => {\n    [\n        {\n            model: '220733SG',\n            expect: {\n                vendor : DeviceVendor.XIAOMI,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: '5087Z',\n            expect: {\n                vendor : DeviceVendor.TCL,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: '9137W',\n            expect: {\n                vendor : DeviceVendor.TCL,\n                type : DeviceType.TABLET\n            }\n        },\n        {\n            model: 'BE2015',\n            expect: {\n                vendor : DeviceVendor.ONEPLUS,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'CPH2389',\n            expect: {\n                vendor : DeviceVendor.ONEPLUS,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'Infinix X669C',\n            expect: {\n                vendor : DeviceVendor.INFINIX,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'itel L6502',\n            expect: {\n                vendor : DeviceVendor.ITEL,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'Lenovo TB-X606F',\n            expect: {\n                vendor : DeviceVendor.LENOVO,\n                type : DeviceType.TABLET\n            }\n        },\n        {\n            model: 'LM-Q720',\n            expect: {\n                vendor : DeviceVendor.LG,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'M2003J15SC',\n            expect: {\n                vendor : DeviceVendor.XIAOMI,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'MAR-LX1A',\n            expect: {\n                vendor : DeviceVendor.HUAWEI,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'moto g(20)',\n            expect: {\n                vendor : DeviceVendor.MOTOROLA,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'Nokia C210',\n            expect: {\n                vendor : DeviceVendor.NOKIA,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'Pixel 8',\n            expect: {\n                vendor : DeviceVendor.GOOGLE,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'Redmi Note 9S',\n            expect: {\n                vendor : DeviceVendor.XIAOMI,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'RMX3830',\n            expect: {\n                vendor : DeviceVendor.REALME,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'SM-S536DL',\n            expect: {\n                vendor : DeviceVendor.SAMSUNG,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'SM-S546VL',\n            expect: {\n                vendor : DeviceVendor.SAMSUNG,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'SM-T875',\n            expect: {\n                vendor : DeviceVendor.SAMSUNG,\n                type : DeviceType.TABLET\n            }\n        },\n        {\n            model: 'STK-L21',\n            expect: {\n                vendor : DeviceVendor.HUAWEI,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'T430W',\n            expect: {\n                vendor : DeviceVendor.TCL,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'TECNO KI5k',\n            expect: {\n                vendor : DeviceVendor.TECNO,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'vivo 1820',\n            expect: {\n                vendor : DeviceVendor.VIVO,\n                type : DeviceType.MOBILE\n            }\n        },\n        {\n            model: 'Xbox',\n            expect: {\n                vendor : DeviceVendor.MICROSOFT,\n                type : DeviceType.CONSOLE\n            }\n        }\n    ]\n    .forEach(test => {\n        it(`Solve \"${test.model}\"`, () => {\n            const headers = {\n                'sec-ch-ua-model' : test.model,\n            };\n            const { device } = UAParser(headers).withClientHints();\n            assert.strictEqual(device.model, test.model);\n            assert.strictEqual(device.vendor, test.expect.vendor);\n            assert.strictEqual(device.type, test.expect.type);\n        });\n    });\n});\n\ndescribe('Chaining withClientHints() & withFeatureCheck() in server-side development', () => {\n    const headers = {\n        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',\n        'sec-ch-ua-form-factors' : '\"VR\"'\n    };\n    const device = new UAParser(headers).getDevice();\n    it('Chain order: withFeatureCheck().withClientHints()', () => {  \n        const fc2ch = device.withFeatureCheck().withClientHints();\n        assert.strictEqual(fc2ch.type, \"xr\");\n    });\n    it('Chain order: withClientHints().withFeatureCheck()', () => {\n        const ch2fc = device.withClientHints().withFeatureCheck();\n        assert.strictEqual(ch2fc.type, \"xr\");\n    });\n});"
  }
]