![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
content-script-activation
Advanced tools
Simpler injection of content scripts in browser extensions. Inject once, activate on click.
Simpler injection of content scripts in browser extensions. Inject once, activate on click.
npm i content-script-activation
When building a browser extension, it is a common pattern to inject a content script when the extension icon is clicked. This is usually done like this:
browser.action.onClicked.addListener((tab) => {
browser.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"],
});
});
However, the problem is that on every click, the content script is injected again. This can cause trouble depending on how the content script is written. For example, if the content script adds an event listener to the window
object, it will be added again on every click, leading to unexpected behavior.
This package does things differently:
To illustrate this, consider the following sequence of events:
Extension icon clicked
Content script injected
Activation event triggered
Extension icon clicked
Activation event triggered
Extension icon clicked
Activation event triggered
(...)
This model is simpler and lets you think about "activation" as a single event that happens on every click. Script injection is handled for you.
On the service worker:
import { setupContentScriptActivation } from "content-script-activation";
setupContentScriptActivation("content-script.js");
On the content script:
import { setupActivation } from "content-script-activation";
setupActivation(() => {
// do something on activation
});
If you want to inject the content script only on certain tabs, you can pass a filter function to setupContentScriptActivation
:
setupContentScriptActivation({
filterTab: (tab) => tab.url?.startsWith("http"),
inject: "content-script.js",
});
The tab
object (tabs.Tab
type) is the one passed to the browser.action.onClicked.addListener
callback, and contains information about the tab where the extension icon was clicked (such as the ID, URL, title, etc).
If you need to run some code before injection (e.g. preparing a database connection) or after injection (e.g. sending a message to the content script), you can use the beforeInject
and afterInject
options:
setupContentScriptActivation({
inject: {
async beforeInjection(context) {
// ...
},
async afterInjection(context) {
// ...
},
scripts: "content-script.js",
},
});
Both functions can be synchronous or asynchronous. They receive a context
object with information about the tab where the content script is injected.
You can inject stylesheets in a similar way to scripts:
setupContentScriptActivation({
inject: {
// ...
styles: "content-style.css",
},
});
If you need more control over how scripts or stylesheets are injected, you can pass option objects instead of strings:
setupContentScriptActivation({
inject: {
scripts: {
files: ["content-script.js"],
injectImmediately: false,
},
styles: {
files: ["content-style.css"],
origin: "USER",
},
},
});
The options that can be passed correspond to the options that can be passed to browser.scripting.executeScript
and browser.scripting.insertCSS
, except for the target
option (which is always set to the tab where the extension icon was clicked).
You can inject multiple scripts and stylesheets by passing an array of strings or option objects:
setupContentScriptActivation({
inject: {
scripts: ["content-script.js", "content-script-2.js"],
styles: ["content-style.css", "content-style-2.css"],
},
});
Note that you need to call setupActivation
from every content script you want to inject.
For brevity, setupContentScriptActivation
has two shorthand APIs:
If you don't need to pass any other options, you can pass the script or scripts to inject directly in string form:
setupContentScriptActivation("content-script.js");
If you need to pass other options, but don't need any of the inject
options, you can pass the script or scripts to inject directly to inject
:
setupContentScriptActivation({
filterTab: (tab) => tab.url?.startsWith("http"),
inject: "content-script.js",
});
If you don't need to run any code in your content script on activation (for example, if you only want to make sure that the script and styles are only injected once), you can omit the callback when calling setupActivation
:
import { setupActivation } from "content-script-activation";
setupActivation();
Note that you still need to call setupActivation
from every content script you want to inject.
If you want to use setupContentScriptActivation
more than once, you must pass a unique ID to each instance:
// service-worker.js
setupContentScriptActivation({
// ...
inject: "content-script-1.js",
scriptId: "content-script-1",
});
setupContentScriptActivation({
// ...
inject: "content-script-2.js",
scriptId: "content-script-2",
});
// content-script-1.js
setupActivation(() => {
// ...
}, "content-script-1");
// content-script-2.js
setupActivation(() => {
// ...
}, "content-script-2");
An example use case for this is when you want to inject different scripts on different tabs. In this case, you can use the filterTab
option to filter the tabs where each script is injected.
By default, the content script is activated when the extension icon is clicked. For advanced use cases, you can pass false
to the injectOnClick
option. This will disable the default behavior, and setupContentScriptActivation
will return an asynchronous function that you can call to activate the content script manually. The function takes a target as an argument, which corresponds to the target
option of browser.scripting.executeScript
(scripting.InjectionTarget
).
const activate = setupContentScriptActivation({
inject: "content-script.js",
injectOnClick: false,
});
// when you want to activate the content script:
await activate({ tabId: myTabId });
All browsers that support the underlying APIs should be supported. This is the case for Chrome and Firefox, and probably all desktop browsers that support extensions in the first place. Cross-browser API namespace compatibility is achieved through the browser-namespace
package.
browser.scripting.removeCSS
.FAQs
Simpler injection of content scripts in browser extensions. Inject once, activate on click.
The npm package content-script-activation receives a total of 10 weekly downloads. As such, content-script-activation popularity was classified as not popular.
We found that content-script-activation demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.