diff --git a/packages/devtools-kit/src/_types/client-api.ts b/packages/devtools-kit/src/_types/client-api.ts index e7d5335ffa..99d3efc92f 100644 --- a/packages/devtools-kit/src/_types/client-api.ts +++ b/packages/devtools-kit/src/_types/client-api.ts @@ -58,7 +58,7 @@ export interface NuxtDevtoolsHostClient { /** * Refreshes the client */ - refreshState(): NuxtDevtoolsHostClient + refreshState(iframe?: HTMLIFrameElement): NuxtDevtoolsHostClient } export interface NuxtDevtoolsClient { @@ -74,6 +74,8 @@ export interface NuxtDevtoolsClient { } export interface NuxtDevtoolsIframeClient { + url: string + version: string host: NuxtDevtoolsHostClient devtools: NuxtDevtoolsClient } diff --git a/packages/devtools-ui-kit/package.json b/packages/devtools-ui-kit/package.json index 0180b5c721..65ab32cb46 100644 --- a/packages/devtools-ui-kit/package.json +++ b/packages/devtools-ui-kit/package.json @@ -40,7 +40,7 @@ "@nuxt/devtools": "workspace:*", "@nuxt/devtools-kit": "workspace:*", "@nuxt/kit": "^3.5.3", - "@nuxtjs/color-mode": "^3.2.0", + "@nuxtjs/color-mode": "^3.3.0", "@unocss/core": "^0.53.1", "@unocss/nuxt": "^0.53.1", "@unocss/preset-attributify": "^0.53.1", diff --git a/packages/devtools-webext/extension/devtools.html b/packages/devtools-webext/extension/devtools.html new file mode 100644 index 0000000000..f42224d245 --- /dev/null +++ b/packages/devtools-webext/extension/devtools.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/devtools-webext/extension/icon.png b/packages/devtools-webext/extension/icon.png new file mode 100644 index 0000000000..22af08e79d Binary files /dev/null and b/packages/devtools-webext/extension/icon.png differ diff --git a/packages/devtools-webext/extension/index.html b/packages/devtools-webext/extension/index.html new file mode 100644 index 0000000000..e04c867aa3 --- /dev/null +++ b/packages/devtools-webext/extension/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/packages/devtools-webext/extension/manifest.json b/packages/devtools-webext/extension/manifest.json new file mode 100644 index 0000000000..a674bf9d7f --- /dev/null +++ b/packages/devtools-webext/extension/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "Nuxt DevTools", + "description": "Unleash Nuxt Developer Experience.", + "version": "0.0.1", + "manifest_version": 3, + "devtools_page": "devtools.html", + "content_security_policy": { + "extension_pages": "script-src 'self' http://localhost:3000; object-src 'self';" + }, + "icons": { + "16": "icon.png", + "48": "icon.png", + "128": "icon.png" + } +} diff --git a/packages/devtools-webext/package.json b/packages/devtools-webext/package.json new file mode 100644 index 0000000000..533096fcdf --- /dev/null +++ b/packages/devtools-webext/package.json @@ -0,0 +1,17 @@ +{ + "name": "@nuxt/devtools-webext", + "private": true, + "type": "module", + "version": "0.6.1", + "license": "MIT", + "scripts": { + "build": "tsup", + "dev": "tsup --watch" + }, + "devDependencies": { + "@types/webextension-polyfill": "^0.10.0", + "tsup": "^7.0.0", + "webext-bridge": "^6.0.1", + "webextension-polyfill": "^0.10.0" + } +} diff --git a/packages/devtools-webext/src/content.ts b/packages/devtools-webext/src/content.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/devtools-webext/src/devtools.ts b/packages/devtools-webext/src/devtools.ts new file mode 100644 index 0000000000..f891530559 --- /dev/null +++ b/packages/devtools-webext/src/devtools.ts @@ -0,0 +1,3 @@ +import browser from 'webextension-polyfill' + +browser.devtools.panels.create('Nuxt', 'icon.png', 'index.html') diff --git a/packages/devtools-webext/src/panel.ts b/packages/devtools-webext/src/panel.ts new file mode 100644 index 0000000000..7600bd7574 --- /dev/null +++ b/packages/devtools-webext/src/panel.ts @@ -0,0 +1,83 @@ +/* eslint-disable eslint-comments/no-unlimited-disable */ +import browser from 'webextension-polyfill' + +async function run() { + const [url, isException] = await browser.devtools.inspectedWindow.eval('window.__NUXT_DEVTOOLS_URL__') + // eslint-disable-next-line no-console + console.log({ url, isException }) + + if (!url) + return noDevTools() + + // #1 - inline html + // const origin = new URL(result.url).origin + // const html = await fetch(result.url).then(res => res.text()) + // const body = html.match(/]*>([\s\S]*)<\/body>/i) + // ?.[1] + // ?.replace(/ src="\//, ` src="${origin}/`) + + // if (!body) + // return noDevTools() + + // const div = document.createElement('div') + // div.innerHTML = body + // document.body.appendChild(div) + + // #2 iframe + // const iframe = document.createElement('iframe') + // iframe.src = url + // iframe.style.border = 'none' + // iframe.style.outline = 'none' + // iframe.style.width = '100vw' + // iframe.style.height = '100vh' + // document.body.appendChild(iframe) + + // #3 - Import inline + const html = await fetch(url).then(res => res.text()) + const elements = Array.from((new DOMParser().parseFromString(html, 'text/html')).body.children) + const origin = new URL(url).origin + + const div = document.createElement('div') + div.id = '__nuxt' + document.body.appendChild(div) + + setupColorMode() + window.__NUXT_DEVTOOLS_SERVER_ORIGIN__ = origin + window.__NUXT__ ||= {} + window.__NUXT__.config = { public: { }, app: { baseURL: '/__nuxt_devtools__/client', buildAssetsDir: '/_nuxt/', cdnURL: '' } } + + window.history.replaceState('', '', window.__NUXT__.config.app.baseURL) + + for (const element of elements) { + if (element.tagName === 'SCRIPT') { + if ('src' in element && element.src) { + const url = new URL(element.src as string) + await import(origin + url.pathname) + } + else { + // Manifest V3 does not support eval, we might need to workaround this later + // const script = document.createElement('script') + // script.innerHTML = element.innerHTML + // document.body.appendChild(script) + } + } + else { + div.appendChild(element) + } + } +} + +function noDevTools() { + const div = document.createElement('div') + div.innerText = 'Nuxt devtools not found' + document.body.appendChild(div) +} + +function setupColorMode() { + /* eslint-disable */ + // @ts-expect-error cast + const w=window,de=document.documentElement,knownColorSchemes=["dark","light"],preference=window.localStorage.getItem("nuxt-color-mode")||"system";let value=preference==="system"?getColorScheme():preference;const forcedColorMode=de.getAttribute("data-color-mode-forced");forcedColorMode&&(value=forcedColorMode),addColorScheme(value),w["__NUXT_COLOR_MODE__"]={preference,value,getColorScheme,addColorScheme,removeColorScheme};function addColorScheme(e){const o=""+e+"",t="";de.classList?de.classList.add(o):de.className+=" "+o,t&&de.setAttribute("data-"+t,e)}function removeColorScheme(e){const o=""+e+"",t="";de.classList?de.classList.remove(o):de.className=de.className.replace(new RegExp(o,"g"),""),t&&de.removeAttribute("data-"+t)}function prefersColorScheme(e){return w.matchMedia("(prefers-color-scheme"+e+")")}function getColorScheme(){if(w.matchMedia&&prefersColorScheme("").media!=="not all"){for(const e of knownColorSchemes)if(prefersColorScheme(":"+e).matches)return e}return"light"} + /* eslint-enable */ +} + +run() diff --git a/packages/devtools-webext/tsup.config.ts b/packages/devtools-webext/tsup.config.ts new file mode 100644 index 0000000000..e2b8362192 --- /dev/null +++ b/packages/devtools-webext/tsup.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: [ + './src/*.ts', + ], + outDir: './extension/dist', + format: ['iife'], + outExtension() { + return { js: '.js' } + }, +}) diff --git a/packages/devtools/client/components/AssetFontPreview.vue b/packages/devtools/client/components/AssetFontPreview.vue index d589d1c8c5..1e450d1b2b 100644 --- a/packages/devtools/client/components/AssetFontPreview.vue +++ b/packages/devtools/client/components/AssetFontPreview.vue @@ -11,7 +11,7 @@ const id = computed(() => `devtools-assets-${hash(props.asset)}`) useStyleTag(computed(() => ` @font-face { font-family: '${id.value}'; - src: url('${props.asset.publicPath}'); + src: url('${resolveAssetPath(props.asset.publicPath)}'); } `)) diff --git a/packages/devtools/client/components/AssetPreview.vue b/packages/devtools/client/components/AssetPreview.vue index 457bd35bea..76cb548549 100644 --- a/packages/devtools/client/components/AssetPreview.vue +++ b/packages/devtools/client/components/AssetPreview.vue @@ -10,7 +10,7 @@ defineProps<{