Skip to content
This repository was archived by the owner on May 7, 2026. It is now read-only.

Commit a748bb5

Browse files
authored
feat(extension): add browser extension package with Chrome MV3 and Firefox MV2 (#97)
1 parent a7d59bf commit a748bb5

69 files changed

Lines changed: 7164 additions & 2214 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/browser-extension.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@qwik.dev/devtools': minor
3+
---
4+
5+
feat: add browser extension for Chrome and Firefox
6+
7+
New browser extension package that brings Qwik DevTools to the browser's DevTools panel. Features real-time component tree, state inspection, element picker, hover highlight, live render events, and SPA navigation support. Works standalone or alongside the Vite plugin overlay.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"description": "Qwik devtools monorepo",
55
"scripts": {
66
"playground": "MODE=dev DEBUG=qwik:devtools:* pnpm --filter playground dev",
7+
"ext:dev": "pnpm --filter @devtools/browser-extension dev",
8+
"ext:dev:firefox": "pnpm --filter @devtools/browser-extension dev:firefox",
9+
"ext:build": "pnpm --filter @devtools/browser-extension build",
10+
"ext:build:firefox": "pnpm --filter @devtools/browser-extension build:firefox",
711
"build": "tsx scripts/build-devtools.ts",
812
"change": "changeset",
913
"release": "changeset publish",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.output/
2+
node_modules/
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ESNext",
4+
"module": "ESNext",
5+
"moduleResolution": "Bundler",
6+
"noEmit": true,
7+
"esModuleInterop": true,
8+
"forceConsistentCasingInFileNames": true,
9+
"resolveJsonModule": true,
10+
"strict": true,
11+
"skipLibCheck": true,
12+
"paths": {
13+
"@": ["../src"],
14+
"@/*": ["../src/*"],
15+
"~": ["../src"],
16+
"~/*": ["../src/*"],
17+
"@@": [".."],
18+
"@@/*": ["../*"],
19+
"~~": [".."],
20+
"~~/*": ["../*"]
21+
}
22+
},
23+
"include": [
24+
"../**/*",
25+
"./wxt.d.ts"
26+
],
27+
"exclude": ["../.output"]
28+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Generated by wxt
2+
interface ImportMetaEnv {
3+
readonly MANIFEST_VERSION: 2 | 3;
4+
readonly BROWSER: string;
5+
readonly CHROME: boolean;
6+
readonly FIREFOX: boolean;
7+
readonly SAFARI: boolean;
8+
readonly EDGE: boolean;
9+
readonly OPERA: boolean;
10+
readonly COMMAND: "build" | "serve";
11+
readonly ENTRYPOINT: string;
12+
}
13+
interface ImportMeta {
14+
readonly env: ImportMetaEnv
15+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Generated by wxt
2+
import "wxt/browser";
3+
4+
declare module "wxt/browser" {
5+
/**
6+
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
7+
*/
8+
interface GetMessageOptions {
9+
/**
10+
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
11+
*/
12+
escapeLt?: boolean
13+
}
14+
15+
export interface WxtI18n extends I18n.Static {
16+
/**
17+
* The extension or app ID; you might use this string to construct URLs for resources inside the extension. Even unlocalized extensions can use this message.
18+
* Note: You can't use this message in a manifest file.
19+
*
20+
* "<browser.runtime.id>"
21+
*/
22+
getMessage(
23+
messageName: "@@extension_id",
24+
substitutions?: string | string[],
25+
options?: GetMessageOptions,
26+
): string;
27+
/**
28+
* "<browser.i18n.getUiLocale()>"
29+
*/
30+
getMessage(
31+
messageName: "@@ui_locale",
32+
substitutions?: string | string[],
33+
options?: GetMessageOptions,
34+
): string;
35+
/**
36+
* The text direction for the current locale, either "ltr" for left-to-right languages such as English or "rtl" for right-to-left languages such as Japanese.
37+
*
38+
* "<ltr|rtl>"
39+
*/
40+
getMessage(
41+
messageName: "@@bidi_dir",
42+
substitutions?: string | string[],
43+
options?: GetMessageOptions,
44+
): string;
45+
/**
46+
* If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".
47+
*
48+
* "<rtl|ltr>"
49+
*/
50+
getMessage(
51+
messageName: "@@bidi_reversed_dir",
52+
substitutions?: string | string[],
53+
options?: GetMessageOptions,
54+
): string;
55+
/**
56+
* If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".
57+
*
58+
* "<left|right>"
59+
*/
60+
getMessage(
61+
messageName: "@@bidi_start_edge",
62+
substitutions?: string | string[],
63+
options?: GetMessageOptions,
64+
): string;
65+
/**
66+
* If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".
67+
*
68+
* "<right|left>"
69+
*/
70+
getMessage(
71+
messageName: "@@bidi_end_edge",
72+
substitutions?: string | string[],
73+
options?: GetMessageOptions,
74+
): string;
75+
getMessage(
76+
messageName: "@@extension_id" | "@@ui_locale" | "@@bidi_dir" | "@@bidi_reversed_dir" | "@@bidi_start_edge" | "@@bidi_end_edge",
77+
substitutions?: string | string[],
78+
options?: GetMessageOptions,
79+
): string;
80+
}
81+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Generated by wxt
2+
// Types for the #import virtual module
3+
declare module '#imports' {
4+
export { browser, Browser } from 'wxt/browser';
5+
export { storage, StorageArea, WxtStorage, WxtStorageItem, StorageItemKey, StorageAreaChanges, MigrationError } from 'wxt/utils/storage';
6+
export { getAppConfig, useAppConfig } from 'wxt/utils/app-config';
7+
export { ContentScriptContext, WxtWindowEventMap } from 'wxt/utils/content-script-context';
8+
export { createIframeUi, IframeContentScriptUi, IframeContentScriptUiOptions } from 'wxt/utils/content-script-ui/iframe';
9+
export { createIntegratedUi, IntegratedContentScriptUi, IntegratedContentScriptUiOptions } from 'wxt/utils/content-script-ui/integrated';
10+
export { createShadowRootUi, ShadowRootContentScriptUi, ShadowRootContentScriptUiOptions } from 'wxt/utils/content-script-ui/shadow-root';
11+
export { ContentScriptUi, ContentScriptUiOptions, ContentScriptOverlayAlignment, ContentScriptAppendMode, ContentScriptInlinePositioningOptions, ContentScriptOverlayPositioningOptions, ContentScriptModalPositioningOptions, ContentScriptPositioningOptions, ContentScriptAnchoredOptions, AutoMountOptions, StopAutoMount, AutoMount } from 'wxt/utils/content-script-ui/types';
12+
export { defineAppConfig, WxtAppConfig } from 'wxt/utils/define-app-config';
13+
export { defineBackground } from 'wxt/utils/define-background';
14+
export { defineContentScript } from 'wxt/utils/define-content-script';
15+
export { defineUnlistedScript } from 'wxt/utils/define-unlisted-script';
16+
export { defineWxtPlugin } from 'wxt/utils/define-wxt-plugin';
17+
export { injectScript, ScriptPublicPath, InjectScriptOptions } from 'wxt/utils/inject-script';
18+
export { InvalidMatchPattern, MatchPattern } from 'wxt/utils/match-patterns';
19+
export { fakeBrowser } from 'wxt/testing';
20+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Generated by wxt
2+
import "wxt/browser";
3+
4+
declare module "wxt/browser" {
5+
export type PublicPath =
6+
| ""
7+
| "/"
8+
| "/background.js"
9+
| "/content-scripts/content.js"
10+
| "/devtools-hook.js"
11+
| "/devtools.html"
12+
| "/icon-128.png"
13+
| "/icon-16.png"
14+
| "/icon-32.png"
15+
| "/icon-48.png"
16+
| "/inspect-hook.js"
17+
| "/nav-hook.js"
18+
| "/panel.html"
19+
| "/qwikloader.js"
20+
| "/theme-init.js"
21+
| "/vnode-bridge.js"
22+
type HtmlPublicPath = Extract<PublicPath, `${string}.html`>
23+
export interface WxtRuntime {
24+
getURL(path: PublicPath): string;
25+
getURL(path: `${HtmlPublicPath}${string}`): string;
26+
}
27+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Generated by wxt
2+
/// <reference types="wxt/vite-builder-env" />
3+
/// <reference path="./types/paths.d.ts" />
4+
/// <reference path="./types/i18n.d.ts" />
5+
/// <reference path="./types/globals.d.ts" />
6+
/// <reference path="./types/imports-module.d.ts" />
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "@devtools/browser-extension",
3+
"description": "Qwik DevTools browser extension for Chrome and Firefox",
4+
"version": "0.1.0",
5+
"private": true,
6+
"type": "module",
7+
"scripts": {
8+
"dev": "wxt",
9+
"dev:firefox": "wxt --browser firefox",
10+
"build": "wxt build",
11+
"build:firefox": "wxt build --browser firefox",
12+
"zip": "wxt zip",
13+
"zip:firefox": "wxt zip --browser firefox",
14+
"test": "vitest run",
15+
"test:watch": "vitest",
16+
"lint": "eslint src/"
17+
},
18+
"dependencies": {
19+
"lit": "^3.3.2",
20+
"wxt": "^0.20.20"
21+
},
22+
"devDependencies": {
23+
"@devtools/kit": "workspace:*",
24+
"@types/chrome": "^0.1.38",
25+
"typescript": "5.9.3",
26+
"vitest": "^4.1.0"
27+
}
28+
}

0 commit comments

Comments
 (0)