{"id":12661,"library":"webext-tools","title":"Web Extension Utility Functions","description":"webext-tools provides a collection of modular utility functions designed to simplify common tasks when developing Web Extensions for browsers like Chrome, Firefox, and Safari. The current stable version is 4.0.0, which exclusively targets Manifest V3. The package emphasizes modularity, with each utility function available via its own entry point, allowing developers to import only the specific tools they need and reducing bundle size. This approach differentiates it from monolithic utility libraries. While there isn't an explicit release cadence mentioned, the project sees active development and releases major versions periodically with breaking changes, consistently adapting to browser API changes.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/fregante/webext-tools","tags":["javascript","extension","chrome","firefox","safari","web","extensions","execute","function"],"install":[{"cmd":"npm install webext-tools","lang":"bash","label":"npm"},{"cmd":"yarn add webext-tools","lang":"bash","label":"yarn"},{"cmd":"pnpm add webext-tools","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Since v4.0.0, each utility is a default export from its specific file path. The old single-entry point named import no longer works.","wrong":"import { doesTabExist } from 'webext-tools';","symbol":"doesTabExist","correct":"import doesTabExist from 'webext-tools/does-tab-exist.js';"},{"note":"Introduced in v3.0.0. As of v4.0.0, it must be imported from its dedicated file. Primarily designed for ESM usage in modern browser extensions.","wrong":"const createContextMenu = require('webext-tools/create-context-menu');","symbol":"createContextMenu","correct":"import createContextMenu from 'webext-tools/create-context-menu.js';"},{"note":"Introduced in v1.2.0, supports MV3 since v1.2.3. Requires specific file import since v4.0.0.","wrong":"import { setActionPopup } from 'webext-tools';","symbol":"setActionPopup","correct":"import setActionPopup from 'webext-tools/set-action-popup.js';"},{"note":"Added in v4.0.0. Follows the per-file default export pattern. Requires a valid extension context to use `browser.runtime.getURL` internally.","wrong":"import * as tools from 'webext-tools'; tools.getExtensionUrl();","symbol":"getExtensionUrl","correct":"import getExtensionUrl from 'webext-tools/get-extension-url.js';"}],"quickstart":{"code":"import createContextMenu from 'webext-tools/create-context-menu.js';\nimport getExtensionUrl from 'webext-tools/get-extension-url.js';\nimport setActionPopup from 'webext-tools/set-action-popup.js';\n\n// This polyfill/mock ensures `browser` API is available for demonstration purposes\n// In a real Web Extension, `browser` is globally available.\nconst browser = globalThis.browser || {\n  tabs: {\n    create: (options) => console.log('Creating tab:', options.url)\n  },\n  contextMenus: {\n    create: (options) => {\n      console.log(`Creating context menu: ID='${options.id}', Title='${options.title}', Contexts='${options.contexts}'`);\n      // Simulate adding an onclick listener\n      if (options.onclick) {\n        console.log('Context menu handler registered.');\n        // In a real extension, this would react to actual clicks.\n      }\n    }\n  },\n  action: {\n    setPopup: (options) => console.log('Setting action popup:', options.popup)\n  },\n  runtime: {\n    getURL: (path) => `chrome-extension://your_extension_id/${path}`,\n    onInstalled: { addListener: (cb) => cb() }, // Mock event listener\n    onStartup: { addListener: (cb) => cb() } // Mock event listener\n  }\n};\n\nasync function setupExtensionUtilities() {\n  // Create a context menu item that opens an extension page\n  createContextMenu({\n    id: 'open-webext-page',\n    title: 'Open Example Page (webext-tools)',\n    contexts: ['page', 'selection'],\n    onclick: (info, tab) => {\n      if (tab?.url) {\n        console.log(`Context menu clicked on URL: ${tab.url}`);\n        browser.tabs.create({\n          url: getExtensionUrl('pages/example.html'),\n          active: true\n        });\n      }\n    }\n  });\n\n  // Dynamically set the browser action popup to an HTML file within the extension\n  setActionPopup('pages/popup.html');\n\n  console.log('webext-tools utilities initialized in background script.');\n}\n\n// Ensure setup runs when the extension loads or updates\nbrowser.runtime.onInstalled.addListener(setupExtensionUtilities);\nbrowser.runtime.onStartup.addListener(setupExtensionUtilities);\n","lang":"typescript","description":"This quickstart demonstrates how to import and use several `webext-tools` utilities within a Web Extension's background script, including creating a context menu and setting the browser action popup. It includes a mock `browser` API for basic local execution understanding, though it requires a real extension environment."},"warnings":[{"fix":"Update all imports from `import { someTool } from 'webext-tools';` to `import someTool from 'webext-tools/some-tool.js';`.","message":"The package no longer offers a single entry point. All utilities must now be imported individually from their specific file paths.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Ensure your extension's `manifest.json` specifies `manifest_version: 3`. If still on MV2, you must migrate your extension or use an older version of `webext-tools`.","message":"Support for Manifest V2 (MV2) has been completely dropped. The package now exclusively targets Manifest V3 (MV3).","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Review all calls to `createContextMenu` and ensure the `contexts` array contains only valid, type-safe values as per the updated API definitions.","message":"The `createContextMenu` function now enforces stricter typing for its `contexts` parameter.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"If you used `addOptionsContextMenu`, you need to install and import it from `webext-bugs` directly or implement the equivalent logic yourself.","message":"The `addOptionsContextMenu` functionality has been moved out of `webext-tools` and into the `webext-bugs` package.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Replace calls to `canAccessTab` with direct usage of the relevant functions from `webext-content-scripts` or implement custom tab access logic.","message":"The `canAccessTab` function was removed in favor of directly using functionality from the `webext-content-scripts` package.","severity":"breaking","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Change the import statement from `import { doesTabExist } from 'webext-tools';` to `import doesTabExist from 'webext-tools/does-tab-exist.js';`","cause":"Attempting to use a utility function like `doesTabExist` via a named import or after incorrect CommonJS `require` syntax, which is no longer supported for individual tools since v4.0.0.","error":"TypeError: Cannot read properties of undefined (reading 'doesTabExist')"},{"fix":"Update your extension's `manifest.json` to specify `\"manifest_version\": 3` and migrate any other MV2-specific APIs to their MV3 equivalents.","cause":"Using `webext-tools` version 4.0.0 or higher in an extension configured with `manifest_version: 2`.","error":"Extension is running in Manifest V2, but requires Manifest V3."},{"fix":"Review the Web Extension API documentation for `contextMenus.create` and the `webext-tools` types for `createContextMenu` to use valid `contexts` strings (e.g., 'page', 'selection', 'link').","cause":"Passing an invalid or deprecated string value to the `contexts` array of `createContextMenu` after the type strictness increase in v4.0.0.","error":"Error: Invalid value for property 'contexts'. (Received: \"all\")."}],"ecosystem":"npm"}