From 05833b65873a41f65ea74ad6f368ff2cf9cee890 Mon Sep 17 00:00:00 2001 From: Arlo Date: Sat, 3 Aug 2024 21:26:46 +0800 Subject: [PATCH] feat(extension): support open-in-editor (#543) --- docs/.vitepress/config.ts | 1 + docs/getting-started/open-in-editor.md | 75 +++++++++++++++++++ .../applet/src/modules/components/index.vue | 2 +- .../client/src/composables/open-in-editor.ts | 7 +- .../src/core/open-in-editor/index.ts | 19 +++-- packages/playground/basic/src/main.ts | 5 ++ 6 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 docs/getting-started/open-in-editor.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index ba4f18798..314950f20 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -7,6 +7,7 @@ const GETTING_STARTED: DefaultTheme.NavItemWithLink[] = [ { text: 'Introduction', link: '/getting-started/introduction' }, { text: 'Installation', link: '/getting-started/installation' }, { text: 'Features', link: '/getting-started/features' }, + { text: 'Open in editor', link: '/getting-started/open-in-editor' }, ] const GUIDES: DefaultTheme.NavItemWithLink[] = [ diff --git a/docs/getting-started/open-in-editor.md b/docs/getting-started/open-in-editor.md new file mode 100644 index 000000000..4d9851196 --- /dev/null +++ b/docs/getting-started/open-in-editor.md @@ -0,0 +1,75 @@ +# Open component in editor + +When you select a component, you have the option to open the corresponding source file in your code editor. + +## Used in devtools vite plugin + +Vite plugin supports this feature out-of-the-box. + +The feature is based on the [vite-plugin-vue-inspector](https://github.com/webfansplz/vite-plugin-vue-inspector) plugin and requires configuration, which you can do by looking at the [configuration documentation](https://github.com/webfansplz/vite-plugin-vue-inspector?tab=readme-ov-file#--configuration-ide--editor). + +Starting from **v7.2.0**, you can specify the editor by `launchEditor` option: + +This is a list of [supported editors](https://github.com/yyx990803/launch-editor?tab=readme-ov-file#supported-editors), please ensure that the editor's environment variables are correctly configured beforehand. + +```ts +import VueDevTools from 'vite-plugin-vue-devtools' +export default defineConfig({ + plugins: [ + VueDevTools({ + launchEditor: 'webstorm', + }), + Unocss(), + ], +}) +``` + +## Used in devtools browser extension + +### Vite & Nuxt & Quasar CLI + +Vite & Nuxt & Quasar CLI supports this feature out-of-the-box. Make sure to be in debug mode. + +### Webpack + +In your Vue project, install the [launch-editor-middleware](https://github.com/yyx990803/launch-editor#middleware) package and modify your webpack configuration: + +1. Import the package: + +```ts +const openInEditor = require('launch-editor-middleware') +``` + +2. In the `devServer` option, register the `/__open-in-editor` HTTP route: + +```js +devServer: { + before: (app) => { + app.use('/__open-in-editor', openInEditor()) + } +} +``` + +3. The editor to launch is guessed. You can also specify the editor app with the editor option. See the [supported editors list.](https://github.com/yyx990803/launch-editor?tab=readme-ov-file#supported-editors) + +```js +openInEditor('code') +``` + +4. You can now click on the name of the component in the Component inspector pane (if the devtools knows about its file source, a tooltip will appear). + +### Node.js + +You can use the [launch-editor](https://github.com/yyx990803/launch-editor) package to setup an HTTP route with the `/__open-in-editor` path. It will receive file as an URL variable. + +### Customize request + +You can change the request host (default `/`) with the following code in your frontend app, e.g. + +```ts +if (process.env.NODE_ENV !== 'production') { + window.VUE_DEVTOOLS_CONFIG = { + openInEditorHost: 'http://localhost:3000/' + } +} +``` diff --git a/packages/applet/src/modules/components/index.vue b/packages/applet/src/modules/components/index.vue index 3e2b57149..208e8cb29 100644 --- a/packages/applet/src/modules/components/index.vue +++ b/packages/applet/src/modules/components/index.vue @@ -321,7 +321,7 @@ function closeComponentRenderCode() { - + diff --git a/packages/client/src/composables/open-in-editor.ts b/packages/client/src/composables/open-in-editor.ts index eeec3d0ee..0463e9a62 100644 --- a/packages/client/src/composables/open-in-editor.ts +++ b/packages/client/src/composables/open-in-editor.ts @@ -1,7 +1,12 @@ import { rpc } from '@vue/devtools-core' +import { isInChromePanel } from '@vue/devtools-shared' export const vueInspectorDetected = ref(false) export const openInEditor = async (file: string) => { - return rpc.value.openInEditor({ file }) + const opts: { file: string, host?: string } = { file } + if (isInChromePanel) { + opts.host = 'chrome-extension' + } + return rpc.value.openInEditor(opts) } diff --git a/packages/devtools-kit/src/core/open-in-editor/index.ts b/packages/devtools-kit/src/core/open-in-editor/index.ts index bcee9df45..65ca37852 100644 --- a/packages/devtools-kit/src/core/open-in-editor/index.ts +++ b/packages/devtools-kit/src/core/open-in-editor/index.ts @@ -6,6 +6,7 @@ export interface OpenInEditorOptions { file?: string line?: number column?: number + host?: string } export function setOpenInEditorBaseUrl(url: string) { @@ -13,14 +14,22 @@ export function setOpenInEditorBaseUrl(url: string) { } export function openInEditor(options: OpenInEditorOptions = {}) { - const { file, baseUrl = window.location.origin, line = 0, column = 0 } = options + const { file, host, baseUrl = window.location.origin, line = 0, column = 0 } = options if (file) { - if (devtoolsState.vitePluginDetected) { + if (host === 'chrome-extension') { + const fileName = file.replace(/\\/g, '\\\\') + // @ts-expect-error skip type check + const _baseUrl = window.VUE_DEVTOOLS_CONFIG?.openInEditorHost ?? '/' + fetch(`${_baseUrl}__open-in-editor?file=${encodeURI(file)}`).then((response) => { + if (!response.ok) { + const msg = `Opening component ${fileName} failed` + console.log(`%c${msg}`, 'color:red') + } + }) + } + else if (devtoolsState.vitePluginDetected) { const _baseUrl = target.__VUE_DEVTOOLS_OPEN_IN_EDITOR_BASE_URL__ ?? baseUrl target.__VUE_INSPECTOR__.openInEditor(_baseUrl, file, line, column) } - else { - // @TODO: support other - } } } diff --git a/packages/playground/basic/src/main.ts b/packages/playground/basic/src/main.ts index 620df2aae..fd488cc2a 100644 --- a/packages/playground/basic/src/main.ts +++ b/packages/playground/basic/src/main.ts @@ -22,6 +22,11 @@ app.use(ElementPlus) // devtools.connect() +// // @ts-expect-error skip type check +// window.VUE_DEVTOOLS_CONFIG = { +// openInEditorHost: 'http://localhost:3000', +// } + const routes: RouteRecordRaw[] = [ { path: '/',