Web Extension Utility Functions
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.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'doesTabExist')
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.fixChange the import statement from `import { doesTabExist } from 'webext-tools';` to `import doesTabExist from 'webext-tools/does-tab-exist.js';` -
Extension is running in Manifest V2, but requires Manifest V3.
cause Using `webext-tools` version 4.0.0 or higher in an extension configured with `manifest_version: 2`.fixUpdate your extension's `manifest.json` to specify `"manifest_version": 3` and migrate any other MV2-specific APIs to their MV3 equivalents. -
Error: Invalid value for property 'contexts'. (Received: "all").
cause Passing an invalid or deprecated string value to the `contexts` array of `createContextMenu` after the type strictness increase in v4.0.0.fixReview 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').
Warnings
- breaking The package no longer offers a single entry point. All utilities must now be imported individually from their specific file paths.
- breaking Support for Manifest V2 (MV2) has been completely dropped. The package now exclusively targets Manifest V3 (MV3).
- breaking The `createContextMenu` function now enforces stricter typing for its `contexts` parameter.
- breaking The `addOptionsContextMenu` functionality has been moved out of `webext-tools` and into the `webext-bugs` package.
- breaking The `canAccessTab` function was removed in favor of directly using functionality from the `webext-content-scripts` package.
Install
-
npm install webext-tools -
yarn add webext-tools -
pnpm add webext-tools
Imports
- doesTabExist
import { doesTabExist } from 'webext-tools';import doesTabExist from 'webext-tools/does-tab-exist.js';
- createContextMenu
const createContextMenu = require('webext-tools/create-context-menu');import createContextMenu from 'webext-tools/create-context-menu.js';
- setActionPopup
import { setActionPopup } from 'webext-tools';import setActionPopup from 'webext-tools/set-action-popup.js';
- getExtensionUrl
import * as tools from 'webext-tools'; tools.getExtensionUrl();
import getExtensionUrl from 'webext-tools/get-extension-url.js';
Quickstart
import createContextMenu from 'webext-tools/create-context-menu.js';
import getExtensionUrl from 'webext-tools/get-extension-url.js';
import setActionPopup from 'webext-tools/set-action-popup.js';
// This polyfill/mock ensures `browser` API is available for demonstration purposes
// In a real Web Extension, `browser` is globally available.
const browser = globalThis.browser || {
tabs: {
create: (options) => console.log('Creating tab:', options.url)
},
contextMenus: {
create: (options) => {
console.log(`Creating context menu: ID='${options.id}', Title='${options.title}', Contexts='${options.contexts}'`);
// Simulate adding an onclick listener
if (options.onclick) {
console.log('Context menu handler registered.');
// In a real extension, this would react to actual clicks.
}
}
},
action: {
setPopup: (options) => console.log('Setting action popup:', options.popup)
},
runtime: {
getURL: (path) => `chrome-extension://your_extension_id/${path}`,
onInstalled: { addListener: (cb) => cb() }, // Mock event listener
onStartup: { addListener: (cb) => cb() } // Mock event listener
}
};
async function setupExtensionUtilities() {
// Create a context menu item that opens an extension page
createContextMenu({
id: 'open-webext-page',
title: 'Open Example Page (webext-tools)',
contexts: ['page', 'selection'],
onclick: (info, tab) => {
if (tab?.url) {
console.log(`Context menu clicked on URL: ${tab.url}`);
browser.tabs.create({
url: getExtensionUrl('pages/example.html'),
active: true
});
}
}
});
// Dynamically set the browser action popup to an HTML file within the extension
setActionPopup('pages/popup.html');
console.log('webext-tools utilities initialized in background script.');
}
// Ensure setup runs when the extension loads or updates
browser.runtime.onInstalled.addListener(setupExtensionUtilities);
browser.runtime.onStartup.addListener(setupExtensionUtilities);