Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/browser-extension.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@qwik.dev/devtools': minor
---

feat: add browser extension for Chrome and Firefox

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.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
"description": "Qwik devtools monorepo",
"scripts": {
"playground": "MODE=dev DEBUG=qwik:devtools:* pnpm --filter playground dev",
"ext:dev": "pnpm --filter @devtools/browser-extension dev",
"ext:dev:firefox": "pnpm --filter @devtools/browser-extension dev:firefox",
"ext:build": "pnpm --filter @devtools/browser-extension build",
"ext:build:firefox": "pnpm --filter @devtools/browser-extension build:firefox",
"build": "tsx scripts/build-devtools.ts",
"change": "changeset",
"release": "changeset publish",
Expand Down
2 changes: 2 additions & 0 deletions packages/browser-extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.output/
node_modules/
28 changes: 28 additions & 0 deletions packages/browser-extension/.wxt/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"noEmit": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"@": ["../src"],
"@/*": ["../src/*"],
"~": ["../src"],
"~/*": ["../src/*"],
"@@": [".."],
"@@/*": ["../*"],
"~~": [".."],
"~~/*": ["../*"]
}
},
"include": [
"../**/*",
"./wxt.d.ts"
],
"exclude": ["../.output"]
}
15 changes: 15 additions & 0 deletions packages/browser-extension/.wxt/types/globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Generated by wxt
interface ImportMetaEnv {
readonly MANIFEST_VERSION: 2 | 3;
readonly BROWSER: string;
readonly CHROME: boolean;
readonly FIREFOX: boolean;
readonly SAFARI: boolean;
readonly EDGE: boolean;
readonly OPERA: boolean;
readonly COMMAND: "build" | "serve";
readonly ENTRYPOINT: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
81 changes: 81 additions & 0 deletions packages/browser-extension/.wxt/types/i18n.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Generated by wxt
import "wxt/browser";

declare module "wxt/browser" {
/**
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
*/
interface GetMessageOptions {
/**
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
*/
escapeLt?: boolean
}

export interface WxtI18n extends I18n.Static {
/**
* 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.
* Note: You can't use this message in a manifest file.
*
* "<browser.runtime.id>"
*/
getMessage(
messageName: "@@extension_id",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
/**
* "<browser.i18n.getUiLocale()>"
*/
getMessage(
messageName: "@@ui_locale",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
/**
* 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.
*
* "<ltr|rtl>"
*/
getMessage(
messageName: "@@bidi_dir",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
/**
* If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".
*
* "<rtl|ltr>"
*/
getMessage(
messageName: "@@bidi_reversed_dir",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
/**
* If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".
*
* "<left|right>"
*/
getMessage(
messageName: "@@bidi_start_edge",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
/**
* If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".
*
* "<right|left>"
*/
getMessage(
messageName: "@@bidi_end_edge",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
getMessage(
messageName: "@@extension_id" | "@@ui_locale" | "@@bidi_dir" | "@@bidi_reversed_dir" | "@@bidi_start_edge" | "@@bidi_end_edge",
substitutions?: string | string[],
options?: GetMessageOptions,
): string;
}
}
20 changes: 20 additions & 0 deletions packages/browser-extension/.wxt/types/imports-module.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Generated by wxt
// Types for the #import virtual module
declare module '#imports' {
export { browser, Browser } from 'wxt/browser';
export { storage, StorageArea, WxtStorage, WxtStorageItem, StorageItemKey, StorageAreaChanges, MigrationError } from 'wxt/utils/storage';
export { getAppConfig, useAppConfig } from 'wxt/utils/app-config';
export { ContentScriptContext, WxtWindowEventMap } from 'wxt/utils/content-script-context';
export { createIframeUi, IframeContentScriptUi, IframeContentScriptUiOptions } from 'wxt/utils/content-script-ui/iframe';
export { createIntegratedUi, IntegratedContentScriptUi, IntegratedContentScriptUiOptions } from 'wxt/utils/content-script-ui/integrated';
export { createShadowRootUi, ShadowRootContentScriptUi, ShadowRootContentScriptUiOptions } from 'wxt/utils/content-script-ui/shadow-root';
export { ContentScriptUi, ContentScriptUiOptions, ContentScriptOverlayAlignment, ContentScriptAppendMode, ContentScriptInlinePositioningOptions, ContentScriptOverlayPositioningOptions, ContentScriptModalPositioningOptions, ContentScriptPositioningOptions, ContentScriptAnchoredOptions, AutoMountOptions, StopAutoMount, AutoMount } from 'wxt/utils/content-script-ui/types';
export { defineAppConfig, WxtAppConfig } from 'wxt/utils/define-app-config';
export { defineBackground } from 'wxt/utils/define-background';
export { defineContentScript } from 'wxt/utils/define-content-script';
export { defineUnlistedScript } from 'wxt/utils/define-unlisted-script';
export { defineWxtPlugin } from 'wxt/utils/define-wxt-plugin';
export { injectScript, ScriptPublicPath, InjectScriptOptions } from 'wxt/utils/inject-script';
export { InvalidMatchPattern, MatchPattern } from 'wxt/utils/match-patterns';
export { fakeBrowser } from 'wxt/testing';
}
27 changes: 27 additions & 0 deletions packages/browser-extension/.wxt/types/paths.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Generated by wxt
import "wxt/browser";

declare module "wxt/browser" {
export type PublicPath =
| ""
| "/"
| "/background.js"
| "/content-scripts/content.js"
| "/devtools-hook.js"
| "/devtools.html"
| "/icon-128.png"
| "/icon-16.png"
| "/icon-32.png"
| "/icon-48.png"
| "/inspect-hook.js"
| "/nav-hook.js"
| "/panel.html"
| "/qwikloader.js"
| "/theme-init.js"
| "/vnode-bridge.js"
type HtmlPublicPath = Extract<PublicPath, `${string}.html`>
export interface WxtRuntime {
getURL(path: PublicPath): string;
getURL(path: `${HtmlPublicPath}${string}`): string;
}
}
6 changes: 6 additions & 0 deletions packages/browser-extension/.wxt/wxt.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Generated by wxt
/// <reference types="wxt/vite-builder-env" />
/// <reference path="./types/paths.d.ts" />
/// <reference path="./types/i18n.d.ts" />
/// <reference path="./types/globals.d.ts" />
/// <reference path="./types/imports-module.d.ts" />
28 changes: 28 additions & 0 deletions packages/browser-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "@devtools/browser-extension",
"description": "Qwik DevTools browser extension for Chrome and Firefox",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "wxt",
"dev:firefox": "wxt --browser firefox",
"build": "wxt build",
"build:firefox": "wxt build --browser firefox",
"zip": "wxt zip",
"zip:firefox": "wxt zip --browser firefox",
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint src/"
},
"dependencies": {
"lit": "^3.3.2",
"wxt": "^0.20.20"
},
"devDependencies": {
"@devtools/kit": "workspace:*",
"@types/chrome": "^0.1.38",
"typescript": "5.9.3",
"vitest": "^4.1.0"
}
}
Loading