@@ -4,6 +4,7 @@ import fs from 'node:fs'
44import { bold , dim , green , yellow } from 'kolorist'
55import { normalizePath } from 'vite'
66import type { PluginOption , ServerOptions } from 'vite'
7+ import MagicString from 'magic-string'
78import { compileSFCTemplate } from './compiler'
89import { idToFile , parseVueRequest } from './utils'
910
@@ -88,6 +89,15 @@ export interface VitePluginInspectorOptions {
8889 * @default false
8990 */
9091 disableInspectorOnEditorOpen ?: boolean
92+
93+ /**
94+ * Hide information in VNode and produce clean html in DevTools
95+ *
96+ * Currently, it only works for Vue 3
97+ *
98+ * @default true
99+ */
100+ cleanHtml ?: boolean
91101}
92102
93103const toggleComboKeysMap = {
@@ -125,88 +135,136 @@ function VitePluginInspector(options: VitePluginInspectorOptions = DEFAULT_INSPE
125135 let serverOptions : ServerOptions | undefined
126136
127137 const {
138+ vue,
128139 appendTo,
140+ cleanHtml = vue === 3 , // Only enabled for Vue 3 by default
129141 } = normalizedOptions
130142
131- return {
132- name : 'vite-plugin-vue-inspector' ,
133- enforce : 'pre' ,
134- apply ( _ , { command } ) {
135- // apply only on serve and not for test
136- return command === 'serve' && process . env . NODE_ENV !== 'test'
137- } ,
138- async resolveId ( importee : string ) {
139- if ( importee . startsWith ( 'virtual:vue-inspector-options' ) ) {
140- return importee
141- }
142- else if ( importee . startsWith ( 'virtual:vue-inspector-path:' ) ) {
143- const resolved = importee . replace ( 'virtual:vue-inspector-path:' , `${ inspectorPath } /` )
144- return resolved
145- }
146- } ,
143+ return [
144+ {
145+ name : 'vite-plugin-vue-inspector' ,
146+ enforce : 'pre' ,
147+ apply ( _ , { command } ) {
148+ // apply only on serve and not for test
149+ return command === 'serve' && process . env . NODE_ENV !== 'test'
150+ } ,
151+ async resolveId ( importee : string ) {
152+ if ( importee . startsWith ( 'virtual:vue-inspector-options' ) ) {
153+ return importee
154+ }
155+ else if ( importee . startsWith ( 'virtual:vue-inspector-path:' ) ) {
156+ const resolved = importee . replace ( 'virtual:vue-inspector-path:' , `${ inspectorPath } /` )
157+ return resolved
158+ }
159+ } ,
147160
148- async load ( id ) {
149- if ( id === 'virtual:vue-inspector-options' ) {
150- return `export default ${ JSON . stringify ( { ...normalizedOptions , serverOptions } ) } `
151- }
152- else if ( id . startsWith ( inspectorPath ) ) {
153- const { query } = parseVueRequest ( id )
154- if ( query . type )
155- return
156- // read file ourselves to avoid getting shut out by vites fs.allow check
157- const file = idToFile ( id )
158- if ( fs . existsSync ( file ) )
159- return await fs . promises . readFile ( file , 'utf-8' )
160- else
161- console . error ( `failed to find file for vue-inspector: ${ file } , referenced by id ${ id } .` )
162- }
163- } ,
164- transform ( code , id ) {
165- const { filename, query } = parseVueRequest ( id )
161+ async load ( id ) {
162+ if ( id === 'virtual:vue-inspector-options' ) {
163+ return `export default ${ JSON . stringify ( { ...normalizedOptions , serverOptions } ) } `
164+ }
165+ else if ( id . startsWith ( inspectorPath ) ) {
166+ const { query } = parseVueRequest ( id )
167+ if ( query . type )
168+ return
169+ // read file ourselves to avoid getting shut out by vites fs.allow check
170+ const file = idToFile ( id )
171+ if ( fs . existsSync ( file ) )
172+ return await fs . promises . readFile ( file , 'utf-8' )
173+ else
174+ console . error ( `failed to find file for vue-inspector: ${ file } , referenced by id ${ id } .` )
175+ }
176+ } ,
177+ transform ( code , id ) {
178+ const { filename, query } = parseVueRequest ( id )
166179
167- const isJsx = filename . endsWith ( '.jsx' ) || filename . endsWith ( '.tsx' ) || ( filename . endsWith ( '.vue' ) && query . isJsx )
168- const isTpl = filename . endsWith ( '.vue' ) && query . type !== 'style' && ! query . raw
180+ const isJsx = filename . endsWith ( '.jsx' ) || filename . endsWith ( '.tsx' ) || ( filename . endsWith ( '.vue' ) && query . isJsx )
181+ const isTpl = filename . endsWith ( '.vue' ) && query . type !== 'style' && ! query . raw
169182
170- if ( isJsx || isTpl )
171- return compileSFCTemplate ( { code, id : filename , type : isJsx ? 'jsx' : 'template' } )
183+ if ( isJsx || isTpl )
184+ return compileSFCTemplate ( { code, id : filename , type : isJsx ? 'jsx' : 'template' } )
172185
173- if ( ! appendTo )
174- return
186+ if ( ! appendTo )
187+ return
175188
176- if ( ( typeof appendTo === 'string' && filename . endsWith ( appendTo ) )
189+ if ( ( typeof appendTo === 'string' && filename . endsWith ( appendTo ) )
177190 || ( appendTo instanceof RegExp && appendTo . test ( filename ) ) )
178- return { code : `${ code } \nimport 'virtual:vue-inspector-path:load.js'` }
179- } ,
180- configureServer ( server ) {
181- const _printUrls = server . printUrls
182- const { toggleComboKey } = normalizedOptions
183-
184- toggleComboKey && ( server . printUrls = ( ) => {
185- const keys = normalizeComboKeyPrint ( toggleComboKey )
186- _printUrls ( )
187- console . log ( ` ${ green ( '➜' ) } ${ bold ( 'Vue Inspector' ) } : ${ green ( `Press ${ yellow ( keys ) } in App to toggle the Inspector` ) } \n` )
188- } )
189- } ,
190- transformIndexHtml ( html ) {
191- if ( appendTo )
192- return
193- return {
194- html,
195- tags : [
196- {
197- tag : 'script' ,
198- injectTo : 'head' ,
199- attrs : {
200- type : 'module' ,
201- src : '/@id/virtual:vue-inspector-path:load.js' ,
191+ return { code : `${ code } \nimport 'virtual:vue-inspector-path:load.js'` }
192+ } ,
193+ configureServer ( server ) {
194+ const _printUrls = server . printUrls
195+ const { toggleComboKey } = normalizedOptions
196+
197+ toggleComboKey && ( server . printUrls = ( ) => {
198+ const keys = normalizeComboKeyPrint ( toggleComboKey )
199+ _printUrls ( )
200+ console . log ( ` ${ green ( '➜' ) } ${ bold ( 'Vue Inspector' ) } : ${ green ( `Press ${ yellow ( keys ) } in App to toggle the Inspector` ) } \n` )
201+ } )
202+ } ,
203+ transformIndexHtml ( html ) {
204+ if ( appendTo )
205+ return
206+ return {
207+ html,
208+ tags : [
209+ {
210+ tag : 'script' ,
211+ injectTo : 'head' ,
212+ attrs : {
213+ type : 'module' ,
214+ src : '/@id/virtual:vue-inspector-path:load.js' ,
215+ } ,
202216 } ,
203- } ,
204- ] ,
205- }
206- } ,
207- configResolved ( resolvedConfig ) {
208- serverOptions = resolvedConfig . server
217+ ] ,
218+ }
219+ } ,
220+ configResolved ( resolvedConfig ) {
221+ serverOptions = resolvedConfig . server
222+ } ,
209223 } ,
224+ {
225+ name : 'vite-plugin-vue-inspector:post' ,
226+ enforce : 'post' ,
227+ apply ( _ , { command } ) {
228+ // apply only on serve and not for test
229+ return cleanHtml && vue === 3 && command === 'serve' && process . env . NODE_ENV !== 'test'
230+ } ,
231+ transform ( code ) {
232+ if ( code . includes ( '_interopVNode' ) )
233+ return
234+ if ( ! code . includes ( 'data-v-inspector' ) )
235+ return
236+
237+ const fn = new Set < string > ( )
238+ const s = new MagicString ( code )
239+
240+ s . replace ( / ( c r e a t e E l e m e n t V N o d e | c r e a t e V N o d e | c r e a t e E l e m e n t B l o c k ) a s _ \1, ? / g, ( _ , name ) => {
241+ fn . add ( name )
242+ return ''
243+ } )
244+
245+ if ( ! fn . size )
246+ return
247+
248+ s . appendLeft ( 0 , `/* Injection by vite-plugin-vue-inspector Start */
249+ import { ${ Array . from ( fn . values ( ) ) . map ( i => `${ i } as __${ i } ` ) . join ( ',' ) } } from 'vue'
250+ function _interopVNode(vnode) {
251+ if (vnode && vnode.props && 'data-v-inspector' in vnode.props) {
252+ const data = vnode.props['data-v-inspector']
253+ delete vnode.props['data-v-inspector']
254+ Object.defineProperty(vnode.props, '__v_inspector', { value: data, enumerable: false })
210255 }
256+ return vnode
257+ }
258+ ${ Array . from ( fn . values ( ) ) . map ( i => `function _${ i } (...args) { return _interopVNode(__${ i } (...args)) }` ) . join ( '\n' ) }
259+ /* Injection by vite-plugin-vue-inspector End */
260+ ` )
261+
262+ return {
263+ code : s . toString ( ) ,
264+ map : s . generateMap ( { hires : 'boundary' } ) ,
265+ }
266+ } ,
267+ } ,
268+ ]
211269}
212270export default VitePluginInspector
0 commit comments