extension 3.15.0-next.1 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
[npm-version-url]: https://www.npmjs.com/package/extension
|
|
3
3
|
[npm-downloads-image]: https://img.shields.io/npm/dm/extension.svg?color=0971fe
|
|
4
4
|
[npm-downloads-url]: https://www.npmjs.com/package/extension
|
|
5
|
+
[stars-image]: https://img.shields.io/github/stars/extension-js/extension.js?style=flat&color=0971fe
|
|
6
|
+
[stars-url]: https://github.com/extension-js/extension.js/stargazers
|
|
5
7
|
[action-image]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml/badge.svg?branch=main&color=0971fe
|
|
6
8
|
[action-url]: https://github.com/extension-js/extension.js/actions
|
|
7
9
|
[discord-image]: https://img.shields.io/discord/1253608412890271755?label=Discord&logo=discord&style=flat&color=0971fe
|
|
@@ -9,133 +11,166 @@
|
|
|
9
11
|
[snyk-image]: https://snyk.io/test/github/extension-js/extension/badge.svg?color=0971fe
|
|
10
12
|
[snyk-url]: https://snyk.io/test/github/extension-js/extension
|
|
11
13
|
|
|
12
|
-
[![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![CI][action-image]][action-url] [![Discord][discord-image]][discord-url]
|
|
14
|
+
# Extension.js [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![Stars][stars-image]][stars-url] [![CI][action-image]][action-url] [![Discord][discord-image]][discord-url]
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
> The cross-browser extension framework
|
|
16
|
+
> Build extensions for Chrome, Edge, and Firefox. No build config required.
|
|
17
17
|
|
|
18
18
|
<img alt="Logo" align="right" src="https://avatars.githubusercontent.com/u/172809806" width="15.5%" />
|
|
19
19
|
|
|
20
|
-
- [Create a new extension](#create-a-new-extension) — How to create a new extension.
|
|
21
|
-
- [Watch demo](#watch-demo) — See how creating a new extension works.
|
|
22
|
-
- [Start from an example](https://github.com/extension-js/examples) — Start from a working baseline.
|
|
23
|
-
- [I have an extension](#i-have-an-extension) — Use only specific parts of Extension.js.
|
|
24
|
-
|
|
25
|
-
Create cross-browser extensions without manual build configuration.<br />Use Extension.js to develop, build, and preview across browsers with a unified workflow.
|
|
26
|
-
|
|
27
|
-
## Create a new extension
|
|
28
|
-
|
|
29
|
-
Use the `create` command to generate a new extension. Also works with pnpm, yarn, and bun.
|
|
30
|
-
|
|
31
20
|
```bash
|
|
32
21
|
npx extension@latest create my-extension
|
|
33
22
|
cd my-extension
|
|
34
23
|
npm run dev
|
|
35
24
|
```
|
|
36
25
|
|
|
37
|
-
|
|
26
|
+
Works with `npm`, `pnpm`, `yarn`, and `bun`.
|
|
27
|
+
|
|
28
|
+
[Documentation](https://extension.js.org) · [Templates](https://templates.extension.dev) · [Examples](https://github.com/extension-js/examples) · [Discord](https://discord.gg/v9h2RgeTSN)
|
|
29
|
+
|
|
30
|
+
## Why Extension.js
|
|
31
|
+
|
|
32
|
+
Browser extensions ship with the worst dev experience in modern web. Manifest V3 fragmentation, browser-specific quirks, no hot reload for content scripts, and a separate build pipeline for every target. Extension.js fixes that.
|
|
33
|
+
|
|
34
|
+
- **Hot Module Replacement** for background, content, popup, and options scripts, including React, Vue, Svelte, and Preact components
|
|
35
|
+
- **Manifest V3 by default**, with automatic adapters for Chrome, Edge, and Firefox targets
|
|
36
|
+
- **One CLI** for Chrome, Edge, Firefox, and any Chromium or Gecko binary
|
|
37
|
+
- **Zero config**, no webpack, no rollup, no plugins to maintain
|
|
38
|
+
- **First-class** TypeScript, React, Vue, Svelte, and Preact support
|
|
39
|
+
- **Production builds** with `extension build --zip`, ready for the Chrome Web Store and Firefox Add-ons
|
|
40
|
+
- **Drop-in** for existing extensions with one `devDependency`
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
## Watch it work
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
[60-second demo](https://github.com/cezaraugusto/extension/assets/4672033/7263d368-99c4-434f-a60a-72c489672586)
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
Or skip the install and try a [live template](https://templates.extension.dev) in your browser.
|
|
47
|
+
|
|
48
|
+
## How is this different
|
|
49
|
+
|
|
50
|
+
If you have used [Plasmo](https://www.plasmo.com), [WXT](https://wxt.dev), or [CRXJS](https://crxjs.dev), here is what Extension.js does that the others do not:
|
|
51
|
+
|
|
52
|
+
| Capability | Extension.js |
|
|
53
|
+
| :--------- | :----------- |
|
|
54
|
+
| Run any GitHub sample directly | `extension dev https://github.com/.../sample` |
|
|
55
|
+
| Managed browser binaries | `extension install firefox` downloads an isolated build |
|
|
56
|
+
| Cross-browser HMR for content scripts | Built in, no plugin glue |
|
|
57
|
+
| Production zip for the stores | `extension build --zip` |
|
|
58
|
+
| Framework agnostic | [Vanilla](https://templates.extension.dev/javascript), [TS](https://templates.extension.dev/typescript), [React](https://templates.extension.dev/react), [Vue](https://templates.extension.dev/vue), [Svelte](https://templates.extension.dev/svelte), [Preact](https://templates.extension.dev/preact), no lock-in |
|
|
59
|
+
| Custom Chromium and Gecko binaries | `--chromium-binary`, `--gecko-binary` |
|
|
60
|
+
|
|
61
|
+
## Frameworks
|
|
44
62
|
|
|
45
63
|
<div align="center">
|
|
46
64
|
|
|
47
|
-
| <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/a9e2541a-96f0-4caa-9fc9-5fc5c3e901c8" width="70"> | <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/b42c5330-9e2a-4045-99c3-1f7d264dfaf4" width="70"> | <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/f19edff3-9005-4f50-b05c-fba615896a7f" width="70"> | <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/ff64721d-d145-4213-930d-e70193f8d57e" width="70"> | <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/15f1314a-aa65-4ce2-a3f3-cf53c4f730cf" width="70"> | <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/de1082fd-7cf6-4202-8c12-a5c3cd3e5b42" width="70"> | <img src="https://github.com/cezaraugusto/extension.js/assets/4672033/8807efd9-93e5-4db5-a1d2-9ac524f7ecc2" width="70"> |
|
|
48
|
-
|
|
|
49
|
-
|
|
|
65
|
+
| <img alt="ESNext" src="https://github.com/cezaraugusto/extension.js/assets/4672033/a9e2541a-96f0-4caa-9fc9-5fc5c3e901c8" width="70"> | <img alt="TypeScript" src="https://github.com/cezaraugusto/extension.js/assets/4672033/b42c5330-9e2a-4045-99c3-1f7d264dfaf4" width="70"> | <img alt="WASM" src="https://github.com/cezaraugusto/extension.js/assets/4672033/f19edff3-9005-4f50-b05c-fba615896a7f" width="70"> | <img alt="React" src="https://github.com/cezaraugusto/extension.js/assets/4672033/ff64721d-d145-4213-930d-e70193f8d57e" width="70"> | <img alt="Vue" src="https://github.com/cezaraugusto/extension.js/assets/4672033/15f1314a-aa65-4ce2-a3f3-cf53c4f730cf" width="70"> | <img alt="Svelte" src="https://github.com/cezaraugusto/extension.js/assets/4672033/de1082fd-7cf6-4202-8c12-a5c3cd3e5b42" width="70"> | <img alt="Preact" src="https://github.com/cezaraugusto/extension.js/assets/4672033/8807efd9-93e5-4db5-a1d2-9ac524f7ecc2" width="70"> |
|
|
66
|
+
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
|
|
67
|
+
| ESNext<br>[Try out](https://templates.extension.dev/javascript) | TypeScript<br>[Try out](https://templates.extension.dev/typescript) | WASM<br>[Try out](https://github.com/extension-js/examples/tree/main/examples/sidebar-transformers-js) | React<br>[Try out](https://templates.extension.dev/react) | Vue<br>[Try out](https://templates.extension.dev/vue) | Svelte<br>[Try out](https://templates.extension.dev/svelte) | Preact<br>[Try out](https://templates.extension.dev/preact) |
|
|
50
68
|
|
|
51
69
|
</div>
|
|
52
70
|
|
|
53
|
-
|
|
54
|
-
<summary>Get started from a sample</summary>
|
|
71
|
+
## Browsers
|
|
55
72
|
|
|
56
|
-
|
|
73
|
+
Use these flags with `extension dev`, `extension start`, or `extension preview`:
|
|
57
74
|
|
|
58
|
-
|
|
75
|
+
- Select a browser: `--browser <chrome | edge | firefox>`
|
|
76
|
+
- Custom Chromium binary: `--chromium-binary <path-to-binary>`
|
|
77
|
+
- Custom Gecko (Firefox) binary: `--gecko-binary <path-to-binary>`
|
|
59
78
|
|
|
60
|
-
|
|
79
|
+
```bash
|
|
80
|
+
# Chrome (system default)
|
|
81
|
+
npx extension@latest dev --browser=chrome
|
|
61
82
|
|
|
62
|
-
|
|
83
|
+
# Edge
|
|
84
|
+
npx extension@latest dev --browser=edge
|
|
63
85
|
|
|
64
|
-
|
|
86
|
+
# Custom Chrome/Chromium path
|
|
87
|
+
npx extension@latest dev --chromium-binary "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
65
88
|
|
|
66
|
-
|
|
89
|
+
# Custom Firefox path
|
|
90
|
+
npx extension@latest dev --gecko-binary "/Applications/Firefox.app/Contents/MacOS/firefox"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
<div align="center">
|
|
94
|
+
|
|
95
|
+
| <img alt="Chrome" src="https://media.extension.land/logos/browsers/chrome.svg" width="70"> | <img alt="Edge" src="https://media.extension.land/logos/browsers/edge.svg" width="70"> | <img alt="Firefox" src="https://media.extension.land/logos/browsers/firefox.svg" width="70"> | <img alt="Safari" src="https://media.extension.land/logos/browsers/safari.svg" width="70"> | <img alt="Chromium" src="https://media.extension.land/logos/browsers/chromium.svg" width="70"> | <img alt="Gecko" src="https://media.extension.land/logos/browsers/firefox.svg" width="70"> |
|
|
96
|
+
| :-: | :-: | :-: | :-: | :-: | :-: |
|
|
97
|
+
| Google Chrome<br>✅ Supported | Microsoft Edge<br>✅ Supported | Mozilla Firefox<br>✅ Supported | Apple Safari<br> 🚙 Next | Chromium-based<br>✅ Supported | Gecko-based<br>✅ Supported |
|
|
98
|
+
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
## Ship to the store
|
|
102
|
+
|
|
103
|
+
Build a production-ready bundle and zip it for submission to the Chrome Web Store, Edge Add-ons, or Firefox AMO:
|
|
67
104
|
|
|
68
105
|
```bash
|
|
69
|
-
|
|
106
|
+
# Production build
|
|
107
|
+
npx extension@latest build
|
|
108
|
+
|
|
109
|
+
# Production build packaged as a ZIP
|
|
110
|
+
npx extension@latest build --zip
|
|
111
|
+
|
|
112
|
+
# Per-browser builds
|
|
113
|
+
npx extension@latest build --browser=firefox --zip
|
|
70
114
|
```
|
|
71
115
|
|
|
72
|
-
|
|
116
|
+
Useful flags:
|
|
117
|
+
|
|
118
|
+
- `--zip` packages the build into a ZIP ready for store upload
|
|
119
|
+
- `--zip-source` includes source files for store source-code review
|
|
120
|
+
- `--zip-filename <name>` controls the output filename
|
|
121
|
+
- `--polyfill` enables the cross-browser webextension polyfill
|
|
122
|
+
|
|
123
|
+
## Manage browser binaries
|
|
124
|
+
|
|
125
|
+
Skip the system-install dance. Extension.js can download and manage isolated browser binaries for clean dev sessions:
|
|
73
126
|
|
|
74
|
-
|
|
127
|
+
```bash
|
|
128
|
+
# Install a managed Firefox build
|
|
129
|
+
npx extension@latest install firefox
|
|
75
130
|
|
|
76
|
-
|
|
131
|
+
# Install Chrome and Edge in one go
|
|
132
|
+
npx extension@latest install --browser=all
|
|
77
133
|
|
|
78
|
-
|
|
134
|
+
# Print where managed browsers live
|
|
135
|
+
npx extension@latest install --where
|
|
136
|
+
```
|
|
79
137
|
|
|
80
|
-
|
|
138
|
+
## Add to an existing extension
|
|
81
139
|
|
|
82
|
-
|
|
140
|
+
Install Extension.js as a dev dependency and wire up your scripts.
|
|
83
141
|
|
|
84
142
|
```bash
|
|
85
143
|
npm install extension@latest --save-dev
|
|
86
144
|
```
|
|
87
145
|
|
|
88
|
-
**Step 2 - Link your npm scripts with the executable Extension.js commands**
|
|
89
|
-
|
|
90
146
|
```json
|
|
91
147
|
{
|
|
92
148
|
"scripts": {
|
|
93
149
|
"build": "extension build",
|
|
94
150
|
"dev": "extension dev",
|
|
95
151
|
"preview": "extension preview"
|
|
96
|
-
},
|
|
97
|
-
"devDependencies": {
|
|
98
|
-
// ...other dependencies
|
|
99
|
-
"extension": "latest"
|
|
100
152
|
}
|
|
101
153
|
}
|
|
102
154
|
```
|
|
103
155
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
- To develop the extension, run `npm run dev`.
|
|
107
|
-
- To build the extension in production mode, run `npm run build`.
|
|
108
|
-
- To visualize the extension in production mode, run `npm run build` and `npm run preview`.
|
|
109
|
-
|
|
110
|
-
## Using a specific browser for development
|
|
111
|
-
|
|
112
|
-
| <img src="https://media.extension.land/logos/browsers/chrome.svg" width="70"> | <img src="https://media.extension.land/logos/browsers/edge.svg" width="70"> | <img src="https://media.extension.land/logos/browsers/firefox.svg" width="70"> | <img src="https://media.extension.land/logos/browsers/safari.svg" width="70"> | <img src="https://media.extension.land/logos/browsers/chromium.svg" width="70"> | <img src="https://media.extension.land/logos/browsers/firefox.svg" width="70"> |
|
|
113
|
-
| :---------------------------------------------------------------------------: | :-------------------------------------------------------------------------: | :----------------------------------------------------------------------------: | :---------------------------------------------------------------------------: | :-----------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |
|
|
114
|
-
| Chrome browser<br>✅ | Edge browser<br>✅ | Firefox browser<br>✅ | Safari browser<br>(soon) | Chromium-based<br>✅ | Gecko-based<br>✅ |
|
|
115
|
-
|
|
116
|
-
### Browser flags and custom binaries
|
|
117
|
-
|
|
118
|
-
Use these flags with `extension dev`, `extension start`, or `extension preview`:
|
|
156
|
+
Run `npm run dev` to develop, `npm run build` for production, and `npm run preview` to inspect the production output. [See it in action.](https://github.com/cezaraugusto/extension/assets/4672033/48694a23-b7f1-4098-9c5d-eff49983739c)
|
|
119
157
|
|
|
120
|
-
|
|
121
|
-
- Custom Chromium binary: `--chromium-binary <path-to-binary>`
|
|
122
|
-
- Custom Gecko (Firefox) binary: `--gecko-binary <path-to-binary>`
|
|
158
|
+
## Start from a Chrome sample
|
|
123
159
|
|
|
124
|
-
|
|
160
|
+
Pull any sample from [Chrome Extension Samples](https://github.com/GoogleChrome/chrome-extensions-samples) and run it directly:
|
|
125
161
|
|
|
126
162
|
```bash
|
|
127
|
-
|
|
128
|
-
|
|
163
|
+
npx extension@latest dev https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/sample.page-redder --browser=edge
|
|
164
|
+
```
|
|
129
165
|
|
|
130
|
-
|
|
131
|
-
npx extension@latest dev --browser=edge
|
|
166
|
+
[Watch demo](https://github.com/cezaraugusto/extension/assets/4672033/ee221a94-6ec7-4e04-8553-8812288927f1)
|
|
132
167
|
|
|
133
|
-
|
|
134
|
-
npx extension@latest dev --chromium-binary "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
168
|
+
## Community
|
|
135
169
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
170
|
+
- Star the repo if Extension.js helped you ship faster
|
|
171
|
+
- Join the [Discord](https://discord.gg/v9h2RgeTSN) for help and feedback
|
|
172
|
+
- Open issues and feature requests on [GitHub](https://github.com/extension-js/extension.js/issues)
|
|
173
|
+
- Browse production-ready [examples](https://github.com/extension-js/examples)
|
|
139
174
|
|
|
140
175
|
## Sponsors
|
|
141
176
|
|
package/dist/322.cjs
CHANGED
|
@@ -817,15 +817,23 @@ exports.modules = {
|
|
|
817
817
|
});
|
|
818
818
|
for (const target of matchingTargets){
|
|
819
819
|
const targetId = target?.targetId;
|
|
820
|
-
if (targetId)
|
|
821
|
-
|
|
820
|
+
if (!targetId) continue;
|
|
821
|
+
let sessionId;
|
|
822
|
+
try {
|
|
823
|
+
sessionId = await this.attachToTarget(targetId);
|
|
824
|
+
} catch {
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
try {
|
|
822
828
|
await this.sendCommand('Runtime.enable', {}, sessionId);
|
|
823
|
-
|
|
824
|
-
expression: '(function(){ try { if (!chrome || !chrome.runtime || !chrome.runtime.reload) return false; chrome.runtime.reload(); return true; } catch (error) { return false; } })()',
|
|
825
|
-
returnByValue: true
|
|
826
|
-
}, sessionId);
|
|
829
|
+
} catch {
|
|
827
830
|
return true;
|
|
828
|
-
}
|
|
831
|
+
}
|
|
832
|
+
this.sendCommand('Runtime.evaluate', {
|
|
833
|
+
expression: '(function(){ try { if (!chrome || !chrome.runtime || !chrome.runtime.reload) return false; chrome.runtime.reload(); return true; } catch (error) { return false; } })()',
|
|
834
|
+
returnByValue: true
|
|
835
|
+
}, sessionId).catch(()=>{});
|
|
836
|
+
return true;
|
|
829
837
|
}
|
|
830
838
|
}
|
|
831
839
|
return false;
|
|
@@ -964,6 +972,7 @@ exports.modules = {
|
|
|
964
972
|
let firstEvalId = null;
|
|
965
973
|
let evalIdCount = 0;
|
|
966
974
|
let urlDerivedId = null;
|
|
975
|
+
const versionFallbackIds = [];
|
|
967
976
|
for (const t of targets || []){
|
|
968
977
|
const url = String(t?.url || '');
|
|
969
978
|
const type = String(t?.type || '');
|
|
@@ -994,9 +1003,12 @@ exports.modules = {
|
|
|
994
1003
|
const versionMatches = expectedVersion ? gotVersion === expectedVersion : false;
|
|
995
1004
|
const manifestVersionMatches = expectedManifestVersion ? gotManifestVersion === expectedManifestVersion : false;
|
|
996
1005
|
if (nameMatches && (!profileCandidateId || id === profileCandidateId)) return id;
|
|
997
|
-
if (expectedVersion && versionMatches && (expectedManifestVersion ? manifestVersionMatches : true) && (!profileCandidateId || id === profileCandidateId))
|
|
1006
|
+
if (expectedVersion && versionMatches && (expectedManifestVersion ? manifestVersionMatches : true) && (!profileCandidateId || id === profileCandidateId)) {
|
|
1007
|
+
if (!versionFallbackIds.includes(id)) versionFallbackIds.push(id);
|
|
1008
|
+
}
|
|
998
1009
|
} catch {}
|
|
999
1010
|
}
|
|
1011
|
+
if (1 === versionFallbackIds.length && (expectedName ? !expectedNameIsMsg : true)) return versionFallbackIds[0];
|
|
1000
1012
|
if (1 === evalIdCount && firstEvalId) {
|
|
1001
1013
|
if (!hasExpectedManifestIdentity) return firstEvalId;
|
|
1002
1014
|
deferredFirstEvalId = deferredFirstEvalId || firstEvalId;
|
package/dist/browsers.cjs
CHANGED
|
@@ -14,7 +14,10 @@ var __webpack_modules__ = {
|
|
|
14
14
|
var external_pintor_ = __webpack_require__("pintor");
|
|
15
15
|
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
|
|
16
16
|
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
17
|
-
|
|
17
|
+
const BANNER_PRINTED_EVENT = 'extensionjs:banner-printed';
|
|
18
|
+
function markBannerPrinted() {
|
|
19
|
+
process.emit(BANNER_PRINTED_EVENT);
|
|
20
|
+
}
|
|
18
21
|
const printedKeys = new Set();
|
|
19
22
|
function readUpdateSuffixOnce() {
|
|
20
23
|
const suffix = process.env.EXTENSION_CLI_UPDATE_SUFFIX;
|
|
@@ -251,9 +254,23 @@ var __webpack_modules__ = {
|
|
|
251
254
|
if (!fs__rspack_import_0.existsSync(dir)) return null;
|
|
252
255
|
try {
|
|
253
256
|
const re = new RegExp(`^content-${index}\\.[a-f0-9]+\\.${ext}$`, 'i');
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
let latestPath = null;
|
|
258
|
+
let latestMtimeMs = -1 / 0;
|
|
259
|
+
for (const name of fs__rspack_import_0.readdirSync(dir)){
|
|
260
|
+
if (!re.test(name)) continue;
|
|
261
|
+
const candidate = path__rspack_import_1.join(dir, name);
|
|
262
|
+
try {
|
|
263
|
+
const stat = fs__rspack_import_0.statSync(candidate);
|
|
264
|
+
if (stat.mtimeMs > latestMtimeMs) {
|
|
265
|
+
latestMtimeMs = stat.mtimeMs;
|
|
266
|
+
latestPath = candidate;
|
|
267
|
+
}
|
|
268
|
+
} catch {}
|
|
269
|
+
}
|
|
270
|
+
return latestPath;
|
|
271
|
+
} catch {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
257
274
|
}
|
|
258
275
|
function readContentScriptRules(compilation, extensionRoot) {
|
|
259
276
|
const manifest = readManifestFromCompilation(compilation) || readManifestFromDisk(extensionRoot) || {};
|
|
@@ -1787,8 +1804,10 @@ var __webpack_modules__ = {
|
|
|
1787
1804
|
return p;
|
|
1788
1805
|
}
|
|
1789
1806
|
};
|
|
1790
|
-
if (hasExplicitProfile)
|
|
1791
|
-
|
|
1807
|
+
if (hasExplicitProfile) {
|
|
1808
|
+
const trimmedProfile = rawProfile.trim();
|
|
1809
|
+
userProfilePath = external_path_.isAbsolute(trimmedProfile) ? trimmedProfile : external_path_.resolve(contextDir, trimmedProfile);
|
|
1810
|
+
} else if (useSystemProfile) userProfilePath = '';
|
|
1792
1811
|
else {
|
|
1793
1812
|
const outPath = compilation?.options?.output?.path || external_path_.resolve(process.cwd(), 'dist/chrome');
|
|
1794
1813
|
const distRoot = external_path_.dirname(outPath);
|
|
@@ -4095,7 +4114,7 @@ var __webpack_modules__ = {
|
|
|
4095
4114
|
const rdpPort = this.resolveRdpPort(compilation);
|
|
4096
4115
|
const client = this.client || await this.connectClient(rdpPort);
|
|
4097
4116
|
const normalized = (changedAssets || []).map((n)=>String(n || '')).map((n)=>n.replace(/\\/g, '/'));
|
|
4098
|
-
const isManifestChanged = normalized.
|
|
4117
|
+
const isManifestChanged = normalized.some((n)=>'manifest.json' === n || n.endsWith('/manifest.json'));
|
|
4099
4118
|
const isLocalesChanged = normalized.some((n)=>/(^|\/)__?locales\/.+\.json$/i.test(n));
|
|
4100
4119
|
const isContentScriptChanged = normalized.some((n)=>/(^|\/)content_scripts\/content-\d+(?:\.[a-f0-9]+)?\.(js|css)$/i.test(n));
|
|
4101
4120
|
let isServiceWorkerChanged = false;
|
|
@@ -4107,7 +4126,7 @@ var __webpack_modules__ = {
|
|
|
4107
4126
|
const sw = parsed?.background?.service_worker;
|
|
4108
4127
|
if ('string' == typeof sw && sw) {
|
|
4109
4128
|
const swUnix = sw.replace(/\\/g, '/');
|
|
4110
|
-
isServiceWorkerChanged = normalized.
|
|
4129
|
+
isServiceWorkerChanged = normalized.some((n)=>n === swUnix || n.endsWith('/' + swUnix));
|
|
4111
4130
|
}
|
|
4112
4131
|
}
|
|
4113
4132
|
} catch {}
|
|
@@ -4560,8 +4579,10 @@ var __webpack_modules__ = {
|
|
|
4560
4579
|
return p;
|
|
4561
4580
|
}
|
|
4562
4581
|
};
|
|
4563
|
-
if ('string' == typeof profile && profile.trim().length > 0)
|
|
4564
|
-
|
|
4582
|
+
if ('string' == typeof profile && profile.trim().length > 0) {
|
|
4583
|
+
const trimmedProfile = profile.trim();
|
|
4584
|
+
profilePath = external_path_.isAbsolute(trimmedProfile) ? trimmedProfile : external_path_.resolve(contextDir, trimmedProfile);
|
|
4585
|
+
} else if (useSystemProfile) profilePath = '';
|
|
4565
4586
|
else {
|
|
4566
4587
|
const base = external_path_.resolve(distRoot, 'extension-js', 'profiles', `${browser}-profile`);
|
|
4567
4588
|
const persist = Boolean(configOptions.persistProfile);
|
|
@@ -4648,9 +4669,6 @@ var __webpack_modules__ = {
|
|
|
4648
4669
|
String(debugPort)
|
|
4649
4670
|
] : [],
|
|
4650
4671
|
'--foreground',
|
|
4651
|
-
'--disable-background-timer-throttling',
|
|
4652
|
-
'--disable-backgrounding-occluded-windows',
|
|
4653
|
-
'--disable-renderer-backgrounding',
|
|
4654
4672
|
...additionalArgs
|
|
4655
4673
|
];
|
|
4656
4674
|
return {
|
|
@@ -4671,9 +4689,6 @@ var __webpack_modules__ = {
|
|
|
4671
4689
|
String(debugPort)
|
|
4672
4690
|
] : [],
|
|
4673
4691
|
'--foreground',
|
|
4674
|
-
'--disable-background-timer-throttling',
|
|
4675
|
-
'--disable-backgrounding-occluded-windows',
|
|
4676
|
-
'--disable-renderer-backgrounding',
|
|
4677
4692
|
...additionalArgs
|
|
4678
4693
|
];
|
|
4679
4694
|
return {
|
|
@@ -4982,9 +4997,6 @@ var __webpack_modules__ = {
|
|
|
4982
4997
|
'-wait-for-browser'
|
|
4983
4998
|
] : [],
|
|
4984
4999
|
'--foreground',
|
|
4985
|
-
'--disable-background-timer-throttling',
|
|
4986
|
-
'--disable-backgrounding-occluded-windows',
|
|
4987
|
-
'--disable-renderer-backgrounding',
|
|
4988
5000
|
...firefoxArgs
|
|
4989
5001
|
];
|
|
4990
5002
|
this.child = await this.spawnFirefoxChild(binaryPath, args, wslFallbackBinary);
|
package/dist/cli.cjs
CHANGED
|
@@ -15,7 +15,10 @@ var __webpack_modules__ = {
|
|
|
15
15
|
var external_pintor_ = __webpack_require__("pintor");
|
|
16
16
|
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
|
|
17
17
|
var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
18
|
-
|
|
18
|
+
const BANNER_PRINTED_EVENT = 'extensionjs:banner-printed';
|
|
19
|
+
function markBannerPrinted() {
|
|
20
|
+
process.emit(BANNER_PRINTED_EVENT);
|
|
21
|
+
}
|
|
19
22
|
const printedKeys = new Set();
|
|
20
23
|
function readUpdateSuffixOnce() {
|
|
21
24
|
const suffix = process.env.EXTENSION_CLI_UPDATE_SUFFIX;
|
|
@@ -252,9 +255,23 @@ var __webpack_modules__ = {
|
|
|
252
255
|
if (!fs__rspack_import_0.existsSync(dir)) return null;
|
|
253
256
|
try {
|
|
254
257
|
const re = new RegExp(`^content-${index}\\.[a-f0-9]+\\.${ext}$`, 'i');
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
let latestPath = null;
|
|
259
|
+
let latestMtimeMs = -1 / 0;
|
|
260
|
+
for (const name of fs__rspack_import_0.readdirSync(dir)){
|
|
261
|
+
if (!re.test(name)) continue;
|
|
262
|
+
const candidate = path__rspack_import_1.join(dir, name);
|
|
263
|
+
try {
|
|
264
|
+
const stat = fs__rspack_import_0.statSync(candidate);
|
|
265
|
+
if (stat.mtimeMs > latestMtimeMs) {
|
|
266
|
+
latestMtimeMs = stat.mtimeMs;
|
|
267
|
+
latestPath = candidate;
|
|
268
|
+
}
|
|
269
|
+
} catch {}
|
|
270
|
+
}
|
|
271
|
+
return latestPath;
|
|
272
|
+
} catch {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
258
275
|
}
|
|
259
276
|
function readContentScriptRules(compilation, extensionRoot) {
|
|
260
277
|
const manifest = readManifestFromCompilation(compilation) || readManifestFromDisk(extensionRoot) || {};
|
|
@@ -1786,8 +1803,10 @@ var __webpack_modules__ = {
|
|
|
1786
1803
|
return p;
|
|
1787
1804
|
}
|
|
1788
1805
|
};
|
|
1789
|
-
if (hasExplicitProfile)
|
|
1790
|
-
|
|
1806
|
+
if (hasExplicitProfile) {
|
|
1807
|
+
const trimmedProfile = rawProfile.trim();
|
|
1808
|
+
userProfilePath = external_path_.isAbsolute(trimmedProfile) ? trimmedProfile : external_path_.resolve(contextDir, trimmedProfile);
|
|
1809
|
+
} else if (useSystemProfile) userProfilePath = '';
|
|
1791
1810
|
else {
|
|
1792
1811
|
const outPath = compilation?.options?.output?.path || external_path_.resolve(process.cwd(), 'dist/chrome');
|
|
1793
1812
|
const distRoot = external_path_.dirname(outPath);
|
|
@@ -4094,7 +4113,7 @@ var __webpack_modules__ = {
|
|
|
4094
4113
|
const rdpPort = this.resolveRdpPort(compilation);
|
|
4095
4114
|
const client = this.client || await this.connectClient(rdpPort);
|
|
4096
4115
|
const normalized = (changedAssets || []).map((n)=>String(n || '')).map((n)=>n.replace(/\\/g, '/'));
|
|
4097
|
-
const isManifestChanged = normalized.
|
|
4116
|
+
const isManifestChanged = normalized.some((n)=>'manifest.json' === n || n.endsWith('/manifest.json'));
|
|
4098
4117
|
const isLocalesChanged = normalized.some((n)=>/(^|\/)__?locales\/.+\.json$/i.test(n));
|
|
4099
4118
|
const isContentScriptChanged = normalized.some((n)=>/(^|\/)content_scripts\/content-\d+(?:\.[a-f0-9]+)?\.(js|css)$/i.test(n));
|
|
4100
4119
|
let isServiceWorkerChanged = false;
|
|
@@ -4106,7 +4125,7 @@ var __webpack_modules__ = {
|
|
|
4106
4125
|
const sw = parsed?.background?.service_worker;
|
|
4107
4126
|
if ('string' == typeof sw && sw) {
|
|
4108
4127
|
const swUnix = sw.replace(/\\/g, '/');
|
|
4109
|
-
isServiceWorkerChanged = normalized.
|
|
4128
|
+
isServiceWorkerChanged = normalized.some((n)=>n === swUnix || n.endsWith('/' + swUnix));
|
|
4110
4129
|
}
|
|
4111
4130
|
}
|
|
4112
4131
|
} catch {}
|
|
@@ -4559,8 +4578,10 @@ var __webpack_modules__ = {
|
|
|
4559
4578
|
return p;
|
|
4560
4579
|
}
|
|
4561
4580
|
};
|
|
4562
|
-
if ('string' == typeof profile && profile.trim().length > 0)
|
|
4563
|
-
|
|
4581
|
+
if ('string' == typeof profile && profile.trim().length > 0) {
|
|
4582
|
+
const trimmedProfile = profile.trim();
|
|
4583
|
+
profilePath = external_path_.isAbsolute(trimmedProfile) ? trimmedProfile : external_path_.resolve(contextDir, trimmedProfile);
|
|
4584
|
+
} else if (useSystemProfile) profilePath = '';
|
|
4564
4585
|
else {
|
|
4565
4586
|
const base = external_path_.resolve(distRoot, 'extension-js', 'profiles', `${browser}-profile`);
|
|
4566
4587
|
const persist = Boolean(configOptions.persistProfile);
|
|
@@ -4647,9 +4668,6 @@ var __webpack_modules__ = {
|
|
|
4647
4668
|
String(debugPort)
|
|
4648
4669
|
] : [],
|
|
4649
4670
|
'--foreground',
|
|
4650
|
-
'--disable-background-timer-throttling',
|
|
4651
|
-
'--disable-backgrounding-occluded-windows',
|
|
4652
|
-
'--disable-renderer-backgrounding',
|
|
4653
4671
|
...additionalArgs
|
|
4654
4672
|
];
|
|
4655
4673
|
return {
|
|
@@ -4670,9 +4688,6 @@ var __webpack_modules__ = {
|
|
|
4670
4688
|
String(debugPort)
|
|
4671
4689
|
] : [],
|
|
4672
4690
|
'--foreground',
|
|
4673
|
-
'--disable-background-timer-throttling',
|
|
4674
|
-
'--disable-backgrounding-occluded-windows',
|
|
4675
|
-
'--disable-renderer-backgrounding',
|
|
4676
4691
|
...additionalArgs
|
|
4677
4692
|
];
|
|
4678
4693
|
return {
|
|
@@ -4981,9 +4996,6 @@ var __webpack_modules__ = {
|
|
|
4981
4996
|
'-wait-for-browser'
|
|
4982
4997
|
] : [],
|
|
4983
4998
|
'--foreground',
|
|
4984
|
-
'--disable-background-timer-throttling',
|
|
4985
|
-
'--disable-backgrounding-occluded-windows',
|
|
4986
|
-
'--disable-renderer-backgrounding',
|
|
4987
4999
|
...firefoxArgs
|
|
4988
5000
|
];
|
|
4989
5001
|
this.child = await this.spawnFirefoxChild(binaryPath, args, wslFallbackBinary);
|
|
@@ -6142,6 +6154,7 @@ Cross-Browser Compatibility
|
|
|
6142
6154
|
}
|
|
6143
6155
|
function resolveWorkspaceDevelopRoot(startDir) {
|
|
6144
6156
|
let currentDir = external_path_default().resolve(startDir);
|
|
6157
|
+
if (currentDir.split(external_path_default().sep).includes('node_modules')) return;
|
|
6145
6158
|
for(let depth = 0; depth < 8; depth += 1){
|
|
6146
6159
|
const candidate = external_path_default().join(currentDir, 'programs', 'develop');
|
|
6147
6160
|
const resolved = resolveDevelopRootFromDir(candidate);
|
|
@@ -24,6 +24,14 @@ export declare function isCanonicalContentScriptAsset(assetName: string): boolea
|
|
|
24
24
|
/**
|
|
25
25
|
* Resolves the on-disk file for a canonical content bundle. In development the
|
|
26
26
|
* emitted name may include a fullhash (e.g. content_scripts/content-0.a1b2c3d4.js).
|
|
27
|
+
*
|
|
28
|
+
* Dev mode runs with `output.clean: false`, so successive rebuilds leave old
|
|
29
|
+
* hashed bundles on disk for the same `content-<index>` entry. Returning the
|
|
30
|
+
* first `readdirSync` match would pick a stale bundle whenever the filesystem
|
|
31
|
+
* order doesn't align with write order — and Firefox / Chromium would then
|
|
32
|
+
* `executeScript` an outdated content script, making reload look unreliable.
|
|
33
|
+
* Pick the most recently written match instead so the live reload always
|
|
34
|
+
* reflects the latest rebuild.
|
|
27
35
|
*/
|
|
28
36
|
export declare function resolveEmittedContentScriptFile(extensionOutPath: string, index: number, ext: 'js' | 'css'): string | null;
|
|
29
37
|
export declare function getChangedContentScriptEntryNames(modifiedFilePaths: string[], dependencyPathsByEntry: Map<string, Set<string>>): string[];
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"extension": "./bin/extension.cjs"
|
|
39
39
|
},
|
|
40
40
|
"name": "extension",
|
|
41
|
-
"version": "3.15.0
|
|
41
|
+
"version": "3.15.0",
|
|
42
42
|
"description": "Create cross-browser extensions with no build configuration.",
|
|
43
43
|
"homepage": "https://extension.js.org/",
|
|
44
44
|
"bugs": {
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"cross-spawn": "^7.0.6",
|
|
101
101
|
"edge-location": "2.2.0",
|
|
102
102
|
"firefox-location2": "3.0.0",
|
|
103
|
-
"extension-create": "3.15.0
|
|
104
|
-
"extension-develop": "3.15.0
|
|
105
|
-
"extension-install": "3.15.0
|
|
103
|
+
"extension-create": "3.15.0",
|
|
104
|
+
"extension-develop": "3.15.0",
|
|
105
|
+
"extension-install": "3.15.0",
|
|
106
106
|
"commander": "^14.0.3",
|
|
107
107
|
"pintor": "0.3.0",
|
|
108
108
|
"semver": "^7.7.3",
|