extension 3.0.0-next.62 → 3.0.0-next.67
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 +26 -21
- package/dist/cli-lib/messages.d.ts +9 -0
- package/dist/cli.js +107 -72
- package/dist/utils/normalize-options.d.ts +2 -0
- package/package.json +5 -2
- package/types/css-content.d.ts +8 -0
- package/types/css-modules.d.ts +8 -0
- package/types/extension-develop-shim.d.ts +8 -0
- package/types/images.d.ts +8 -0
- package/types/index.d.ts +9 -1
- package/types/index.ts +8 -0
- package/types/js-frameworks.d.ts +8 -0
- package/types/polyfill.d.ts +8 -0
package/README.md
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
[npm-version-image]: https://img.shields.io/npm/v/extension.svg?color=0971fe
|
|
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
|
+
[npm-downloads-url]: https://www.npmjs.com/package/extension
|
|
5
|
+
[action-image]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml/badge.svg?branch=main&color=0971fe
|
|
4
6
|
[action-url]: https://github.com/extension-js/extension.js/actions
|
|
5
|
-
[discord-image]: https://img.shields.io/discord/1253608412890271755?label=Discord&logo=discord&style=flat&color=
|
|
7
|
+
[discord-image]: https://img.shields.io/discord/1253608412890271755?label=Discord&logo=discord&style=flat&color=0971fe
|
|
6
8
|
[discord-url]: https://discord.gg/v9h2RgeTSN
|
|
7
|
-
[snyk-image]: https://snyk.io/test/github/extension-js/extension/badge.svg?color=
|
|
9
|
+
[snyk-image]: https://snyk.io/test/github/extension-js/extension/badge.svg?color=0971fe
|
|
8
10
|
[snyk-url]: https://snyk.io/test/github/extension-js/extension
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
# Extension.js [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![workflow][action-image]][action-url] [![discord][discord-image]][discord-url]
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
> The cross-browser extension framework
|
|
13
15
|
|
|
14
16
|
<img alt="Logo" align="right" src="https://avatars.githubusercontent.com/u/172809806" width="15.5%" />
|
|
15
17
|
|
|
16
|
-
- [Create
|
|
17
|
-
- [
|
|
18
|
-
- [Start
|
|
19
|
-
- [I have
|
|
18
|
+
- [Create a new extension](#create-a-new-extension) — How to create a new extension.
|
|
19
|
+
- [Watch demo](#watch-demo) — See how creating a new extension works.
|
|
20
|
+
- [Start from an example](https://github.com/extension-js/extension.js/tree/main/examples) — Start from a working baseline.
|
|
21
|
+
- [I have an extension](#i-have-an-extension) — Use only specific parts of Extension.js.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
Create cross-browser extensions with no build configuration.<br />Use Extension.js to develop, build, and preview across browsers with a unified workflow.
|
|
22
24
|
|
|
23
|
-
## Create
|
|
25
|
+
## Create a new extension
|
|
24
26
|
|
|
25
27
|
Use the `create` command to generate a new extension. Also works with pnpm, yarn, and bun.
|
|
26
28
|
|
|
@@ -30,11 +32,11 @@ cd my-extension
|
|
|
30
32
|
npm run dev
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
### Watch
|
|
35
|
+
### Watch demo
|
|
34
36
|
|
|
35
|
-
https://github.com/cezaraugusto/extension/assets/4672033/7263d368-99c4-434f-a60a-72c489672586
|
|
37
|
+
[Watch demo](https://github.com/cezaraugusto/extension/assets/4672033/7263d368-99c4-434f-a60a-72c489672586)
|
|
36
38
|
|
|
37
|
-
## Web
|
|
39
|
+
## Web standards and framework support
|
|
38
40
|
|
|
39
41
|
<!-- For a preview of extensions running these technologies, see the [templates](https://templates.extension.land) website. -->
|
|
40
42
|
|
|
@@ -46,15 +48,18 @@ https://github.com/cezaraugusto/extension/assets/4672033/7263d368-99c4-434f-a60a
|
|
|
46
48
|
|
|
47
49
|
</div>
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
<details>
|
|
52
|
+
<summary>Get started from a sample</summary>
|
|
53
|
+
|
|
54
|
+
## Get started
|
|
50
55
|
|
|
51
56
|
Start developing an extension using a sample from Chrome Extension Samples
|
|
52
57
|
|
|
53
58
|
See the example below where we request the sample [page-redder](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/sample.page-redder) from [Google Chrome Extension Samples](https://github.com/GoogleChrome/chrome-extensions-samples).
|
|
54
59
|
|
|
55
|
-
### Watch
|
|
60
|
+
### Watch demo
|
|
56
61
|
|
|
57
|
-
https://github.com/cezaraugusto/extension/assets/4672033/ee221a94-6ec7-4e04-8553-8812288927f1
|
|
62
|
+
[Watch demo](https://github.com/cezaraugusto/extension/assets/4672033/ee221a94-6ec7-4e04-8553-8812288927f1)
|
|
58
63
|
|
|
59
64
|
### Try Yourself
|
|
60
65
|
|
|
@@ -64,13 +69,13 @@ npx extension@latest dev https://github.com/GoogleChrome/chrome-extensions-sampl
|
|
|
64
69
|
|
|
65
70
|
</details>
|
|
66
71
|
|
|
67
|
-
## I have
|
|
72
|
+
## I have an extension
|
|
68
73
|
|
|
69
74
|
If you have an existing extension which is using a package manager, you can install the Extension.js package and manually create the scripts used to run your extension.
|
|
70
75
|
|
|
71
|
-
### See
|
|
76
|
+
### See how it works
|
|
72
77
|
|
|
73
|
-
https://github.com/cezaraugusto/extension/assets/4672033/48694a23-b7f1-4098-9c5d-eff49983739c
|
|
78
|
+
[See how it works](https://github.com/cezaraugusto/extension/assets/4672033/48694a23-b7f1-4098-9c5d-eff49983739c)
|
|
74
79
|
|
|
75
80
|
**Step 1 - Install extension as a `devDependency`**
|
|
76
81
|
|
|
@@ -133,7 +138,7 @@ npx extension@latest dev --gecko-binary "/Applications/Firefox.app/Contents/MacO
|
|
|
133
138
|
<div align="center">
|
|
134
139
|
<p>
|
|
135
140
|
<span style="font-size:21px; color:black;">Browser testing via</span><br>
|
|
136
|
-
<a href="https://www.lambdatest.com/?utm_source=extensionjs&utm_medium=sponsor" target="_blank">
|
|
141
|
+
<a href="https://www.lambdatest.com/?utm_source=extensionjs&utm_medium=sponsor" target="_blank" rel="noopener noreferrer">
|
|
137
142
|
<img src="https://www.lambdatest.com/blue-logo.png" width="250" height="45" alt="LambdaTest Logo" />
|
|
138
143
|
</a>
|
|
139
144
|
</p>
|
|
@@ -7,6 +7,15 @@ export declare const fmt: {
|
|
|
7
7
|
block(title: string, rows: Array<[string, string]>): string;
|
|
8
8
|
truncate(input: unknown, max?: number): string;
|
|
9
9
|
};
|
|
10
|
+
export declare const commandDescriptions: {
|
|
11
|
+
readonly create: "Creates a new extension from a template (React, TypeScript, Vue, Svelte, etc.)";
|
|
12
|
+
readonly dev: "Starts the development server with hot reloading";
|
|
13
|
+
readonly start: "Builds and starts the extension in production mode";
|
|
14
|
+
readonly preview: "Previews the extension in production mode without building";
|
|
15
|
+
readonly build: "Builds the extension for packaging/distribution";
|
|
16
|
+
readonly cleanup: "Cleans up orphaned instances and frees unused ports";
|
|
17
|
+
};
|
|
18
|
+
export declare function unhandledError(err: unknown): string;
|
|
10
19
|
export declare function updateFailed(err: any): string;
|
|
11
20
|
export declare function checkUpdates(packageJson: Record<string, any>, update: {
|
|
12
21
|
latest: string;
|
package/dist/cli.js
CHANGED
|
@@ -40,13 +40,17 @@ function __webpack_require__(moduleId) {
|
|
|
40
40
|
var __webpack_exports__ = {};
|
|
41
41
|
(()=>{
|
|
42
42
|
const external_commander_namespaceObject = require("commander");
|
|
43
|
-
var package_namespaceObject = JSON.parse('{"license":"MIT","repository":{"type":"git","url":"git+https://github.com/extension-js/extension.js.git","directory":"programs/cli"},"engines":{"node":">=18"},"exports":{".":{"types":"./dist/cli.d.ts","import":"./dist/cli.js","require":"./dist/cli.js"}},"main":"./dist/cli.js","types":"./dist/cli.d.ts","typesVersions":{"*":{"types":["./types/index.d.ts"],"types/*":["./types/*"]}},"files":["dist","types"],"bin":{"extension":"./dist/cli.js"},"name":"extension","version":"3.0.0-next.
|
|
43
|
+
var package_namespaceObject = JSON.parse('{"license":"MIT","repository":{"type":"git","url":"git+https://github.com/extension-js/extension.js.git","directory":"programs/cli"},"engines":{"node":">=18"},"exports":{".":{"types":"./dist/cli.d.ts","import":"./dist/cli.js","require":"./dist/cli.js"}},"main":"./dist/cli.js","types":"./dist/cli.d.ts","typesVersions":{"*":{"types":["./types/index.d.ts"],"types/*":["./types/*"]}},"files":["dist","types"],"bin":{"extension":"./dist/cli.js"},"name":"extension","version":"3.0.0-next.67","description":"Create cross-browser extensions with no build configuration.","homepage":"https://extension.js.org/","bugs":{"url":"https://github.com/extension-js/extension.js/issues"},"author":{"name":"Cezar Augusto","email":"boss@cezaraugusto.net","url":"https://cezaraugusto.com"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"scripts":{"prepublishOnly":"pnpm run compile","compile":"rslib build","watch":"rslib build --watch","test":"vitest run"},"keywords":["zero-config","build","develop","browser","extension","chrome extension","edge extension","firefox extension","safari extension","web","react","typescript","webextension","browser-extension","chrome-extension","firefox-addon","edge-extension","safari-web-extension","manifest-v3","mv3","cross-browser","content-script","background-script","devtools","create-extension","scaffold","starter-template","boilerplate","cli"],"dependencies":{"extension-develop":"^3.0.0-next.67","commander":"^12.1.0","extension-create":"^2.2.0","pintor":"0.3.0","semver":"^7.6.3","update-check":"^1.5.4"},"devDependencies":{"@rslib/core":"^0.6.9","@types/chrome":"^0.0.287","@types/node":"^22.10.1","@types/react":"^19.0.1","@types/react-dom":"^19.0.1","@types/webextension-polyfill":"0.12.3","@types/mock-fs":"^4.13.4","@types/semver":"^7.5.8","mock-fs":"^5.4.1","webextension-polyfill":"^0.12.0","tsconfig":"*","typescript":"5.7.2","vitest":"^3.2.4"}}');
|
|
44
44
|
const external_update_check_namespaceObject = require("update-check");
|
|
45
45
|
var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
|
|
46
46
|
const external_pintor_namespaceObject = require("pintor");
|
|
47
47
|
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
|
|
48
48
|
function getLoggingPrefix(type) {
|
|
49
|
-
|
|
49
|
+
const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
|
|
50
|
+
if (isAuthor) {
|
|
51
|
+
const base = 'error' === type ? 'ERROR Author says' : "\u25BA\u25BA\u25BA Author says";
|
|
52
|
+
return external_pintor_default().brightMagenta(base);
|
|
53
|
+
}
|
|
50
54
|
if ('error' === type) return external_pintor_default().red('ERROR');
|
|
51
55
|
if ('warn' === type) return external_pintor_default().brightYellow("\u25BA\u25BA\u25BA");
|
|
52
56
|
if ('info' === type) return external_pintor_default().gray("\u25BA\u25BA\u25BA");
|
|
@@ -54,11 +58,45 @@ var __webpack_exports__ = {};
|
|
|
54
58
|
}
|
|
55
59
|
const code = (text)=>external_pintor_default().blue(text);
|
|
56
60
|
const arg = (text)=>external_pintor_default().gray(text);
|
|
61
|
+
const fmt = {
|
|
62
|
+
heading: (title)=>external_pintor_default().underline(external_pintor_default().blue(title)),
|
|
63
|
+
label: (k)=>external_pintor_default().gray(k.toUpperCase()),
|
|
64
|
+
val: (v)=>external_pintor_default().underline(v),
|
|
65
|
+
code: (v)=>external_pintor_default().blue(v),
|
|
66
|
+
bullet: (s)=>`- ${s}`,
|
|
67
|
+
block (title, rows) {
|
|
68
|
+
const head = fmt.heading(title);
|
|
69
|
+
const body = rows.map(([k, v])=>`${fmt.label(k)} ${v}`).join('\n');
|
|
70
|
+
return `${head}\n${body}`;
|
|
71
|
+
},
|
|
72
|
+
truncate (input, max = 800) {
|
|
73
|
+
const s = (()=>{
|
|
74
|
+
try {
|
|
75
|
+
return 'string' == typeof input ? input : JSON.stringify(input);
|
|
76
|
+
} catch {
|
|
77
|
+
return String(input);
|
|
78
|
+
}
|
|
79
|
+
})();
|
|
80
|
+
return s.length > max ? s.slice(0, max) + "\u2026" : s;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const commandDescriptions = {
|
|
84
|
+
create: 'Creates a new extension from a template (React, TypeScript, Vue, Svelte, etc.)',
|
|
85
|
+
dev: 'Starts the development server with hot reloading',
|
|
86
|
+
start: 'Builds and starts the extension in production mode',
|
|
87
|
+
preview: 'Previews the extension in production mode without building',
|
|
88
|
+
build: 'Builds the extension for packaging/distribution',
|
|
89
|
+
cleanup: 'Cleans up orphaned instances and frees unused ports'
|
|
90
|
+
};
|
|
91
|
+
function unhandledError(err) {
|
|
92
|
+
const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : fmt.truncate(err);
|
|
93
|
+
return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
|
|
94
|
+
}
|
|
57
95
|
function updateFailed(err) {
|
|
58
96
|
return `${getLoggingPrefix('error')} Failed to check for updates.\n${external_pintor_default().red(String((null == err ? void 0 : err.message) || err))}`;
|
|
59
97
|
}
|
|
60
98
|
function checkUpdates(packageJson, update) {
|
|
61
|
-
return `${getLoggingPrefix('info')} \u{1F9E9} ${external_pintor_default().blue('Extension.js')} update available.\n\nYou are currently using version ${external_pintor_default().red(String(packageJson.version))}. Latest stable is ${external_pintor_default().green(String(update.latest))}.\
|
|
99
|
+
return `${getLoggingPrefix('info')} \u{1F9E9} ${external_pintor_default().blue('Extension.js')} update available.\n\nYou are currently using version ${external_pintor_default().red(String(packageJson.version))}. Latest stable is ${external_pintor_default().green(String(update.latest))}.\nUpdate to the latest stable to get fixes and new features.`;
|
|
62
100
|
}
|
|
63
101
|
function programUserHelp() {
|
|
64
102
|
return `\n${getLoggingPrefix('info')} ${external_pintor_default().underline('Help center for the Extension.js program')}
|
|
@@ -73,22 +111,22 @@ Example
|
|
|
73
111
|
|
|
74
112
|
Available Commands
|
|
75
113
|
- ${code('extension create ' + arg('<project-name|project-path>'))}
|
|
76
|
-
|
|
114
|
+
${commandDescriptions.create}
|
|
77
115
|
|
|
78
116
|
- ${code('extension dev ' + arg('[project-path|remote-url]'))}
|
|
79
|
-
|
|
117
|
+
${commandDescriptions.dev}
|
|
80
118
|
|
|
81
119
|
- ${code('extension start ' + arg('[project-path|remote-url]'))}
|
|
82
|
-
|
|
120
|
+
${commandDescriptions.start}
|
|
83
121
|
|
|
84
122
|
- ${code('extension preview ' + arg('[project-path|remote-url]'))}
|
|
85
|
-
|
|
123
|
+
${commandDescriptions.preview}
|
|
86
124
|
|
|
87
125
|
- ${code('extension build ' + arg('[project-path|remote-url]'))}
|
|
88
|
-
|
|
126
|
+
${commandDescriptions.build}
|
|
89
127
|
|
|
90
128
|
- ${code('extension cleanup')}
|
|
91
|
-
|
|
129
|
+
${commandDescriptions.cleanup}
|
|
92
130
|
|
|
93
131
|
Common Options
|
|
94
132
|
- ${code('--browser')} ${arg('<chrome|edge|firefox|chromium|chromium-based|gecko-based|firefox-based>')} Target browser/engine (default: chrome)
|
|
@@ -429,7 +467,7 @@ Cross-Browser Compatibility
|
|
|
429
467
|
this.track('cli_telemetry_consent', {
|
|
430
468
|
value: 'implicit_opt_in'
|
|
431
469
|
});
|
|
432
|
-
console.log(
|
|
470
|
+
console.log(`${external_pintor_default().gray("\u25BA\u25BA\u25BA system")} [extension] anonymous telemetry helps us improve. Pass --no-telemetry to opt out. Read more in TELEMETRY.md.`);
|
|
433
471
|
}
|
|
434
472
|
}
|
|
435
473
|
}
|
|
@@ -469,6 +507,28 @@ Cross-Browser Compatibility
|
|
|
469
507
|
return argv.includes('--no-telemetry');
|
|
470
508
|
}
|
|
471
509
|
const telemetryDisabled = isTelemetryDisabledFromArgs(process.argv);
|
|
510
|
+
function findManifestJson(projectRoot) {
|
|
511
|
+
const stack = [
|
|
512
|
+
projectRoot
|
|
513
|
+
];
|
|
514
|
+
while(stack.length > 0){
|
|
515
|
+
const dir = stack.pop();
|
|
516
|
+
if (!dir) continue;
|
|
517
|
+
let entries;
|
|
518
|
+
try {
|
|
519
|
+
entries = external_fs_default().readdirSync(dir, {
|
|
520
|
+
withFileTypes: true
|
|
521
|
+
});
|
|
522
|
+
} catch {
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
for (const entry of entries){
|
|
526
|
+
if (entry.isFile() && 'manifest.json' === entry.name) return external_path_default().join(dir, entry.name);
|
|
527
|
+
if (entry.isDirectory() && !entry.name.startsWith('.') && 'node_modules' !== entry.name && 'dist' !== entry.name) stack.push(external_path_default().join(dir, entry.name));
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
472
532
|
const telemetry_cli_telemetry = new Telemetry({
|
|
473
533
|
app: 'extension',
|
|
474
534
|
version: package_namespaceObject.version,
|
|
@@ -488,9 +548,8 @@ Cross-Browser Compatibility
|
|
|
488
548
|
telemetry_cli_telemetry.track('cli_boot', {
|
|
489
549
|
command_guess: invoked
|
|
490
550
|
});
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
if (external_fs_default().existsSync(manifestPath)) {
|
|
551
|
+
const manifestPath = findManifestJson(process.cwd());
|
|
552
|
+
if (manifestPath) {
|
|
494
553
|
const raw = external_fs_default().readFileSync(manifestPath, 'utf8');
|
|
495
554
|
const json = JSON.parse(raw);
|
|
496
555
|
const summary = summarizeManifest(json);
|
|
@@ -553,7 +612,7 @@ Cross-Browser Compatibility
|
|
|
553
612
|
}
|
|
554
613
|
}
|
|
555
614
|
function registerCreateCommand(program, telemetry) {
|
|
556
|
-
program.command('create').arguments('<project-name|project-path>').usage('create <project-name|project-path> [options]').description(
|
|
615
|
+
program.command('create').arguments('<project-name|project-path>').usage('create <project-name|project-path> [options]').description(commandDescriptions.create).option('-t, --template <template-name>', 'specify a template for the created project').option('--install [boolean]', 'whether or not to install the dependencies after creating the project (disabled by default)', parseOptionalBoolean, false).action(async function(pathOrRemoteUrl, { template, install }) {
|
|
557
616
|
const startedAt = Date.now();
|
|
558
617
|
telemetry.track('cli_command_start', {
|
|
559
618
|
command: 'create',
|
|
@@ -583,8 +642,30 @@ Cross-Browser Compatibility
|
|
|
583
642
|
}
|
|
584
643
|
});
|
|
585
644
|
}
|
|
645
|
+
function normalizeSourceOption(source, startingUrl) {
|
|
646
|
+
if (!source) return;
|
|
647
|
+
const hasExplicitSourceString = 'string' == typeof source && 'true' !== String(source).trim().toLowerCase();
|
|
648
|
+
const hasStartingUrl = 'string' == typeof startingUrl && String(startingUrl).trim().length > 0;
|
|
649
|
+
if (!hasExplicitSourceString) return hasStartingUrl ? String(startingUrl) : 'https://example.com';
|
|
650
|
+
return String(source);
|
|
651
|
+
}
|
|
652
|
+
function parseLogContexts(raw) {
|
|
653
|
+
if (!raw || 0 === String(raw).trim().length) return;
|
|
654
|
+
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
655
|
+
const allowed = [
|
|
656
|
+
'background',
|
|
657
|
+
'content',
|
|
658
|
+
'page',
|
|
659
|
+
'sidebar',
|
|
660
|
+
'popup',
|
|
661
|
+
'options',
|
|
662
|
+
'devtools'
|
|
663
|
+
];
|
|
664
|
+
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
665
|
+
return values.length > 0 ? values : void 0;
|
|
666
|
+
}
|
|
586
667
|
function registerDevCommand(program, telemetry) {
|
|
587
|
-
program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description(
|
|
668
|
+
program.command('dev').arguments('[project-path|remote-url]').usage('dev [project-path|remote-url] [options]').description(commandDescriptions.dev).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--no-open', 'do not open the browser automatically (default: open)').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...devOptions }) {
|
|
588
669
|
var _devOptions_polyfill;
|
|
589
670
|
if (devOptions.author || devOptions['authorMode']) {
|
|
590
671
|
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
@@ -603,10 +684,9 @@ Cross-Browser Compatibility
|
|
|
603
684
|
validateVendorsOrExit(list, (invalid, supported)=>{
|
|
604
685
|
console.error(unsupportedBrowserFlag(invalid, supported));
|
|
605
686
|
});
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (!hasExplicitSourceString) devOptions.source = hasStartingUrl ? String(devOptions.startingUrl) : 'https://example.com';
|
|
687
|
+
const normalizedSource = normalizeSourceOption(devOptions.source, devOptions.startingUrl);
|
|
688
|
+
if (normalizedSource) {
|
|
689
|
+
devOptions.source = normalizedSource;
|
|
610
690
|
devOptions.watchSource = true;
|
|
611
691
|
}
|
|
612
692
|
const { extensionDev } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "extension-develop"));
|
|
@@ -631,22 +711,7 @@ Cross-Browser Compatibility
|
|
|
631
711
|
source: devOptions.source,
|
|
632
712
|
watchSource: devOptions.watchSource,
|
|
633
713
|
logLevel: logsOption || devOptions.logLevel || 'off',
|
|
634
|
-
logContexts: (
|
|
635
|
-
const raw = logContextOption || devOptions.logContexts;
|
|
636
|
-
if (!raw || 0 === String(raw).trim().length) return;
|
|
637
|
-
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
638
|
-
const allowed = [
|
|
639
|
-
'background',
|
|
640
|
-
'content',
|
|
641
|
-
'page',
|
|
642
|
-
'sidebar',
|
|
643
|
-
'popup',
|
|
644
|
-
'options',
|
|
645
|
-
'devtools'
|
|
646
|
-
];
|
|
647
|
-
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
648
|
-
return values.length ? values : void 0;
|
|
649
|
-
})(),
|
|
714
|
+
logContexts: parseLogContexts(logContextOption),
|
|
650
715
|
logFormat: devOptions.logFormat || 'pretty',
|
|
651
716
|
logTimestamps: false !== devOptions.logTimestamps,
|
|
652
717
|
logColor: false !== devOptions.logColor,
|
|
@@ -669,9 +734,9 @@ Cross-Browser Compatibility
|
|
|
669
734
|
});
|
|
670
735
|
}
|
|
671
736
|
function registerStartCommand(program, telemetry) {
|
|
672
|
-
program.command('start').arguments('[project-path|remote-url]').usage('start [project-path|remote-url] [options]').description(
|
|
737
|
+
program.command('start').arguments('[project-path|remote-url]').usage('start [project-path|remote-url] [options]').description(commandDescriptions.start).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...startOptions }) {
|
|
673
738
|
var _startOptions_polyfill;
|
|
674
|
-
if (startOptions.author || startOptions
|
|
739
|
+
if (startOptions.author || startOptions.authorMode) {
|
|
675
740
|
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
676
741
|
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
677
742
|
}
|
|
@@ -694,22 +759,7 @@ Cross-Browser Compatibility
|
|
|
694
759
|
});
|
|
695
760
|
const logsOption = startOptions.logs;
|
|
696
761
|
const logContextOption = startOptions.logContext;
|
|
697
|
-
const logContexts = (
|
|
698
|
-
const raw = logContextOption || startOptions.logContexts;
|
|
699
|
-
if (!raw || 0 === String(raw).trim().length) return;
|
|
700
|
-
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
701
|
-
const allowed = [
|
|
702
|
-
'background',
|
|
703
|
-
'content',
|
|
704
|
-
'page',
|
|
705
|
-
'sidebar',
|
|
706
|
-
'popup',
|
|
707
|
-
'options',
|
|
708
|
-
'devtools'
|
|
709
|
-
];
|
|
710
|
-
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
711
|
-
return values.length ? values : void 0;
|
|
712
|
-
})();
|
|
762
|
+
const logContexts = parseLogContexts(logContextOption);
|
|
713
763
|
await extensionStart(pathOrRemoteUrl, {
|
|
714
764
|
mode: 'production',
|
|
715
765
|
profile: startOptions.profile,
|
|
@@ -743,7 +793,7 @@ Cross-Browser Compatibility
|
|
|
743
793
|
});
|
|
744
794
|
}
|
|
745
795
|
function registerPreviewCommand(program, telemetry) {
|
|
746
|
-
program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description(
|
|
796
|
+
program.command('preview').arguments('[project-name]').usage('preview [path-to-remote-extension] [options]').description(commandDescriptions.preview).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').option('--gecko-binary, --firefox-binary <path-to-binary>', 'specify a path to the Gecko binary. This option overrides the --browser setting. Defaults to the system default').option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--log-context <list>', '[experimental] comma-separated contexts to include (background,content,page,sidebar,popup,options,devtools). Use `all` to include all contexts (default)').option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--source [url]', "[experimental] opens the provided URL in Chrome and prints the full, live HTML of the page after content scripts are injected").option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...previewOptions }) {
|
|
747
797
|
if (previewOptions.author || previewOptions['authorMode']) {
|
|
748
798
|
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
749
799
|
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
@@ -770,22 +820,7 @@ Cross-Browser Compatibility
|
|
|
770
820
|
});
|
|
771
821
|
const logsOption = previewOptions.logs;
|
|
772
822
|
const logContextOption = previewOptions.logContext;
|
|
773
|
-
const logContexts = (
|
|
774
|
-
const raw = logContextOption || previewOptions.logContexts;
|
|
775
|
-
if (!raw || 0 === String(raw).trim().length) return;
|
|
776
|
-
if ('all' === String(raw).trim().toLowerCase()) return;
|
|
777
|
-
const allowed = [
|
|
778
|
-
'background',
|
|
779
|
-
'content',
|
|
780
|
-
'page',
|
|
781
|
-
'sidebar',
|
|
782
|
-
'popup',
|
|
783
|
-
'options',
|
|
784
|
-
'devtools'
|
|
785
|
-
];
|
|
786
|
-
const values = String(raw).split(',').map((s)=>s.trim()).filter((s)=>s.length > 0).filter((c)=>allowed.includes(c));
|
|
787
|
-
return values.length ? values : void 0;
|
|
788
|
-
})();
|
|
823
|
+
const logContexts = parseLogContexts(logContextOption);
|
|
789
824
|
await extensionPreview(pathOrRemoteUrl, {
|
|
790
825
|
mode: 'production',
|
|
791
826
|
profile: previewOptions.profile,
|
|
@@ -819,7 +854,7 @@ Cross-Browser Compatibility
|
|
|
819
854
|
});
|
|
820
855
|
}
|
|
821
856
|
function registerBuildCommand(program, telemetry) {
|
|
822
|
-
program.command('build').arguments('[project-name]').usage('build [path-to-remote-extension] [options]').description(
|
|
857
|
+
program.command('build').arguments('[project-name]').usage('build [path-to-remote-extension] [options]').description(commandDescriptions.build).option('--browser <chrome | chromium | edge | firefox | chromium-based | gecko-based | firefox-based>', 'specify a browser/engine to run. Defaults to `chromium`').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false`').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`').option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`').option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'whether or not to open the browser automatically. Defaults to `false`').option('--author, --author-mode', '[internal] enable maintainer diagnostics (does not affect user runtime logs)').action(async function(pathOrRemoteUrl, { browser = 'chromium', ...buildOptions }) {
|
|
823
858
|
if (buildOptions.author || buildOptions['authorMode']) {
|
|
824
859
|
process.env.EXTENSION_AUTHOR_MODE = 'true';
|
|
825
860
|
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
@@ -885,7 +920,7 @@ Cross-Browser Compatibility
|
|
|
885
920
|
process.exit(0);
|
|
886
921
|
}
|
|
887
922
|
extensionJs.parseAsync().catch((err)=>{
|
|
888
|
-
console.error(err);
|
|
923
|
+
console.error(unhandledError(err));
|
|
889
924
|
process.exit(1);
|
|
890
925
|
});
|
|
891
926
|
})();
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare function normalizeSourceOption(source: boolean | string | undefined, startingUrl?: string): string | undefined;
|
|
2
|
+
export declare function parseLogContexts(raw: string | undefined): Array<'background' | 'content' | 'page' | 'sidebar' | 'popup' | 'options' | 'devtools'> | undefined;
|
package/package.json
CHANGED
|
@@ -35,9 +35,12 @@
|
|
|
35
35
|
"extension": "./dist/cli.js"
|
|
36
36
|
},
|
|
37
37
|
"name": "extension",
|
|
38
|
-
"version": "3.0.0-next.
|
|
38
|
+
"version": "3.0.0-next.67",
|
|
39
39
|
"description": "Create cross-browser extensions with no build configuration.",
|
|
40
40
|
"homepage": "https://extension.js.org/",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/extension-js/extension.js/issues"
|
|
43
|
+
},
|
|
41
44
|
"author": {
|
|
42
45
|
"name": "Cezar Augusto",
|
|
43
46
|
"email": "boss@cezaraugusto.net",
|
|
@@ -85,7 +88,7 @@
|
|
|
85
88
|
"cli"
|
|
86
89
|
],
|
|
87
90
|
"dependencies": {
|
|
88
|
-
"extension-develop": "^3.0.0-next.
|
|
91
|
+
"extension-develop": "^3.0.0-next.67",
|
|
89
92
|
"commander": "^12.1.0",
|
|
90
93
|
"extension-create": "^2.2.0",
|
|
91
94
|
"pintor": "0.3.0",
|
package/types/css-content.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
type CSSContentData = Readonly<Record<string, string>>
|
|
2
10
|
|
|
3
11
|
declare module '*.css' {
|
package/types/css-modules.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
type CSSModuleData = Readonly<Record<string, string>>
|
|
2
10
|
|
|
3
11
|
declare module '*.module.css' {
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
declare module 'extension-develop' {
|
|
2
10
|
// These types mirror the public surface of programs/develop/module.ts,
|
|
3
11
|
// but are intentionally loose on the CLI side. The real, precise types
|
package/types/images.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
declare module '*.png' {
|
|
2
10
|
const content: string
|
|
3
11
|
|
package/types/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
/// <reference types="node" />
|
|
2
10
|
/// <reference types="chrome" />
|
|
3
11
|
/// <reference types="./js-frameworks.d.ts" />
|
|
@@ -20,7 +28,7 @@ interface ExtensionEnv {
|
|
|
20
28
|
EXTENSION_PUBLIC_BROWSER: ExtensionBrowser
|
|
21
29
|
EXTENSION_PUBLIC_MODE: ExtensionMode
|
|
22
30
|
EXTENSION_PUBLIC_DESCRIPTION_TEXT: string
|
|
23
|
-
|
|
31
|
+
EXTENSION_PUBLIC_LLM_API_KEY: string
|
|
24
32
|
EXTENSION_AUTHOR_MODE: string
|
|
25
33
|
EXTENSION_PUBLIC_AUTHOR_MODE: string
|
|
26
34
|
}
|
package/types/index.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
/// <reference types="node" />
|
|
2
10
|
/// <reference types="react" />
|
|
3
11
|
/// <reference types="react-dom" />
|
package/types/js-frameworks.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
/// <reference types="react" />
|
|
2
10
|
/// <reference types="react-dom" />
|
|
3
11
|
/// <reference types="svelte" />
|
package/types/polyfill.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// ██████╗██╗ ██╗
|
|
2
|
+
// ██╔════╝██║ ██║
|
|
3
|
+
// ██║ ██║ ██║
|
|
4
|
+
// ██║ ██║ ██║
|
|
5
|
+
// ╚██████╗███████╗██║
|
|
6
|
+
// ╚═════╝╚══════╝╚═╝
|
|
7
|
+
// MIT License (c) 2020–present Cezar Augusto & the Extension.js authors — presence implies inheritance
|
|
8
|
+
|
|
1
9
|
/// <reference types="webextension-polyfill" />
|
|
2
10
|
|
|
3
11
|
declare global {
|