Skip to content

Commit

Permalink
feat!: hide data-v-inspector in html (#81)
Browse files Browse the repository at this point in the history
* feat: hide `data-v-inspector` in html

* fix: unplugin

* fix: only enable `cleanHtml` for Vue 3

* chore: fix typo

---------

Co-authored-by: webfansplz <308241863@qq.com>
  • Loading branch information
antfu and webfansplz committed Oct 3, 2023
1 parent ddcfe1d commit 34dfa21
Show file tree
Hide file tree
Showing 12 changed files with 2,785 additions and 2,359 deletions.
24 changes: 13 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@
"release": "pnpm build && changeset && changeset version && changeset publish"
},
"devDependencies": {
"@antfu/eslint-config": "^0.36.0",
"@changesets/cli": "^2.26.0",
"@types/node": "^20.4.4",
"eslint": "^8.36.0",
"esmo": "^0.16.3",
"fs-extra": "^11.1.0",
"tsup": "^6.6.3",
"tsx": "^3.12.5",
"typescript": "^5.0.2",
"vite": "^4.2.0",
"vue": "^3.2.47"
"@antfu/eslint-config": "^0.43.1",
"@changesets/cli": "^2.26.2",
"@types/node": "^20.8.0",
"eslint": "^8.50.0",
"esmo": "^0.17.0",
"fs-extra": "^11.1.1",
"nodemon": "^3.0.1",
"tsup": "^7.2.0",
"tsx": "^3.13.0",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vite-plugin-inspect": "^0.7.40",
"vue": "^3.3.4"
},
"pnpm": {
"packageExtensions": {
Expand Down
16 changes: 8 additions & 8 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@
"vite": "^3.0.0-0 || ^4.0.0-0"
},
"dependencies": {
"@babel/core": "^7.22.17",
"@babel/plugin-proposal-decorators": "^7.22.15",
"@babel/core": "^7.23.0",
"@babel/plugin-proposal-decorators": "^7.23.0",
"@babel/plugin-syntax-import-attributes": "^7.22.5",
"@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/plugin-transform-typescript": "^7.22.15",
"@vue/babel-plugin-jsx": "^1.1.1",
"@vue/compiler-dom": "^3.2.47",
"kolorist": "^1.7.0",
"magic-string": "^0.30.0"
"@vue/babel-plugin-jsx": "^1.1.5",
"@vue/compiler-dom": "^3.3.4",
"kolorist": "^1.8.0",
"magic-string": "^0.30.4"
},
"devDependencies": {
"@types/babel__core": "^7.20.0",
"unplugin": "^1.3.1"
"@types/babel__core": "^7.20.2",
"unplugin": "^1.5.0"
}
}
17 changes: 11 additions & 6 deletions packages/core/src/Overlay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ const isClient = typeof window !== 'undefined'
const importMetaUrl = isClient ? new URL(import.meta.url) : {}
const protocol = inspectorOptions.serverOptions?.https ? 'https:' : importMetaUrl?.protocol
const hostOpts = inspectorOptions.serverOptions?.host
const host = hostOpts && hostOpts !== true ? hostOpts : importMetaUrl?.hostname
const port = hostOpts && hostOpts !== true ? inspectorOptions.serverOptions?.port : importMetaUrl?.port
const baseUrl = isClient ? inspectorOptions.openInEditorHost || `${protocol}//${host}:${port}` : ''
const host = (hostOpts && hostOpts !== true) ? hostOpts : importMetaUrl?.hostname
const port = (hostOpts && hostOpts !== true) ? inspectorOptions.serverOptions?.port : importMetaUrl?.port
const baseUrl = isClient ? (inspectorOptions.openInEditorHost || `${protocol}//${host}:${port}`) : ''
const KEY_DATA = 'data-v-inspector'
const KEY_IGNORE = 'data-v-inspector-ignore'
const KEY_PROPS_DATA = '__v_inspector'
function getData(el) {
return el?.__vnode?.props?.[KEY_PROPS_DATA] ?? el?.getAttribute?.(KEY_DATA)
}
export default {
name: 'VueInspectorOverlay',
Expand Down Expand Up @@ -94,7 +99,7 @@ export default {
methods: {
toggleEventListener() {
const listener = this.enabled ? document.body.addEventListener : document.body.removeEventListener
listener?.call(document.body, 'mousemove', this.updateLinkParams)
listener?.call(document.body, 'resize', this.closeOverlay, true)
listener?.call(document.body, 'click', this.handleClick, true)
Expand Down Expand Up @@ -138,14 +143,14 @@ export default {
}
}
const ignoreIndex = path.findIndex(node => node?.hasAttribute?.(KEY_IGNORE))
const targetNode = path.slice(ignoreIndex + 1).find(node => node?.hasAttribute?.(KEY_DATA))
const targetNode = path.slice(ignoreIndex + 1).find(node => getData(node))
if (!targetNode) {
return {
targetNode: null,
params: null,
}
}
const match = targetNode.getAttribute(KEY_DATA)?.match(splitRE)
const match = getData(targetNode)?.match(splitRE)
const [_, file, line, column] = match || []
return {
targetNode,
Expand Down
200 changes: 129 additions & 71 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import fs from 'node:fs'
import { bold, dim, green, yellow } from 'kolorist'
import { normalizePath } from 'vite'
import type { PluginOption, ServerOptions } from 'vite'
import MagicString from 'magic-string'
import { compileSFCTemplate } from './compiler'
import { idToFile, parseVueRequest } from './utils'

Expand Down Expand Up @@ -88,6 +89,15 @@ export interface VitePluginInspectorOptions {
* @default false
*/
disableInspectorOnEditorOpen?: boolean

/**
* Hide information in VNode and produce clean html in DevTools
*
* Currently, it only works for Vue 3
*
* @default true
*/
cleanHtml?: boolean
}

const toggleComboKeysMap = {
Expand Down Expand Up @@ -125,88 +135,136 @@ function VitePluginInspector(options: VitePluginInspectorOptions = DEFAULT_INSPE
let serverOptions: ServerOptions | undefined

const {
vue,
appendTo,
cleanHtml = vue === 3, // Only enabled for Vue 3 by default
} = normalizedOptions

return {
name: 'vite-plugin-vue-inspector',
enforce: 'pre',
apply(_, { command }) {
// apply only on serve and not for test
return command === 'serve' && process.env.NODE_ENV !== 'test'
},
async resolveId(importee: string) {
if (importee.startsWith('virtual:vue-inspector-options')) {
return importee
}
else if (importee.startsWith('virtual:vue-inspector-path:')) {
const resolved = importee.replace('virtual:vue-inspector-path:', `${inspectorPath}/`)
return resolved
}
},
return [
{
name: 'vite-plugin-vue-inspector',
enforce: 'pre',
apply(_, { command }) {
// apply only on serve and not for test
return command === 'serve' && process.env.NODE_ENV !== 'test'
},
async resolveId(importee: string) {
if (importee.startsWith('virtual:vue-inspector-options')) {
return importee
}
else if (importee.startsWith('virtual:vue-inspector-path:')) {
const resolved = importee.replace('virtual:vue-inspector-path:', `${inspectorPath}/`)
return resolved
}
},

async load(id) {
if (id === 'virtual:vue-inspector-options') {
return `export default ${JSON.stringify({ ...normalizedOptions, serverOptions })}`
}
else if (id.startsWith(inspectorPath)) {
const { query } = parseVueRequest(id)
if (query.type)
return
// read file ourselves to avoid getting shut out by vites fs.allow check
const file = idToFile(id)
if (fs.existsSync(file))
return await fs.promises.readFile(file, 'utf-8')
else
console.error(`failed to find file for vue-inspector: ${file}, referenced by id ${id}.`)
}
},
transform(code, id) {
const { filename, query } = parseVueRequest(id)
async load(id) {
if (id === 'virtual:vue-inspector-options') {
return `export default ${JSON.stringify({ ...normalizedOptions, serverOptions })}`
}
else if (id.startsWith(inspectorPath)) {
const { query } = parseVueRequest(id)
if (query.type)
return
// read file ourselves to avoid getting shut out by vites fs.allow check
const file = idToFile(id)
if (fs.existsSync(file))
return await fs.promises.readFile(file, 'utf-8')
else
console.error(`failed to find file for vue-inspector: ${file}, referenced by id ${id}.`)
}
},
transform(code, id) {
const { filename, query } = parseVueRequest(id)

const isJsx = filename.endsWith('.jsx') || filename.endsWith('.tsx') || (filename.endsWith('.vue') && query.isJsx)
const isTpl = filename.endsWith('.vue') && query.type !== 'style' && !query.raw
const isJsx = filename.endsWith('.jsx') || filename.endsWith('.tsx') || (filename.endsWith('.vue') && query.isJsx)
const isTpl = filename.endsWith('.vue') && query.type !== 'style' && !query.raw

if (isJsx || isTpl)
return compileSFCTemplate({ code, id: filename, type: isJsx ? 'jsx' : 'template' })
if (isJsx || isTpl)
return compileSFCTemplate({ code, id: filename, type: isJsx ? 'jsx' : 'template' })

if (!appendTo)
return
if (!appendTo)
return

if ((typeof appendTo === 'string' && filename.endsWith(appendTo))
if ((typeof appendTo === 'string' && filename.endsWith(appendTo))
|| (appendTo instanceof RegExp && appendTo.test(filename)))
return { code: `${code}\nimport 'virtual:vue-inspector-path:load.js'` }
},
configureServer(server) {
const _printUrls = server.printUrls
const { toggleComboKey } = normalizedOptions

toggleComboKey && (server.printUrls = () => {
const keys = normalizeComboKeyPrint(toggleComboKey)
_printUrls()
console.log(` ${green('➜')} ${bold('Vue Inspector')}: ${green(`Press ${yellow(keys)} in App to toggle the Inspector`)}\n`)
})
},
transformIndexHtml(html) {
if (appendTo)
return
return {
html,
tags: [
{
tag: 'script',
injectTo: 'head',
attrs: {
type: 'module',
src: '/@id/virtual:vue-inspector-path:load.js',
return { code: `${code}\nimport 'virtual:vue-inspector-path:load.js'` }
},
configureServer(server) {
const _printUrls = server.printUrls
const { toggleComboKey } = normalizedOptions

toggleComboKey && (server.printUrls = () => {
const keys = normalizeComboKeyPrint(toggleComboKey)
_printUrls()
console.log(` ${green('➜')} ${bold('Vue Inspector')}: ${green(`Press ${yellow(keys)} in App to toggle the Inspector`)}\n`)
})
},
transformIndexHtml(html) {
if (appendTo)
return
return {
html,
tags: [
{
tag: 'script',
injectTo: 'head',
attrs: {
type: 'module',
src: '/@id/virtual:vue-inspector-path:load.js',
},
},
},
],
}
},
configResolved(resolvedConfig) {
serverOptions = resolvedConfig.server
],
}
},
configResolved(resolvedConfig) {
serverOptions = resolvedConfig.server
},
},
{
name: 'vite-plugin-vue-inspector:post',
enforce: 'post',
apply(_, { command }) {
// apply only on serve and not for test
return cleanHtml && vue === 3 && command === 'serve' && process.env.NODE_ENV !== 'test'
},
transform(code) {
if (code.includes('_interopVNode'))
return
if (!code.includes('data-v-inspector'))
return

const fn = new Set<string>()
const s = new MagicString(code)

s.replace(/(createElementVNode|createVNode|createElementBlock) as _\1,?/g, (_, name) => {
fn.add(name)
return ''
})

if (!fn.size)
return

s.appendLeft(0, `/* Injection by vite-plugin-vue-inspector Start */
import { ${Array.from(fn.values()).map(i => `${i} as __${i}`).join(',')} } from 'vue'
function _interopVNode(vnode) {
if (vnode && vnode.props && 'data-v-inspector' in vnode.props) {
const data = vnode.props['data-v-inspector']
delete vnode.props['data-v-inspector']
Object.defineProperty(vnode.props, '__v_inspector', { value: data, enumerable: false })
}
return vnode
}
${Array.from(fn.values()).map(i => `function _${i}(...args) { return _interopVNode(__${i}(...args)) }`).join('\n')}
/* Injection by vite-plugin-vue-inspector End */
`)

return {
code: s.toString(),
map: s.generateMap({ hires: 'boundary' }),
}
},
},
]
}
export default VitePluginInspector
2 changes: 1 addition & 1 deletion packages/playground/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"preview": "nuxi preview"
},
"devDependencies": {
"nuxt": "3.3.1",
"nuxt": "3.7.4",
"unplugin-vue-inspector": "workspace:*",
"vite-plugin-vue-inspector": "workspace:*"
}
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/vue2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
"build": "vite build"
},
"dependencies": {
"@vue/composition-api": "^1.7.1",
"@vue/composition-api": "^1.7.2",
"vue": "2.7.14",
"vue-property-decorator": "^9.1.2",
"vue-template-compiler": "2.7.14"
},
"devDependencies": {
"sass": "^1.59.3",
"sass": "^1.68.0",
"unplugin-vue-inspector": "workspace:*",
"vite-plugin-vue-inspector": "workspace:*",
"vite-plugin-vue2": "^1.9.3"
Expand Down
12 changes: 6 additions & 6 deletions packages/playground/vue3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
"name": "playground-vue3",
"private": true,
"scripts": {
"dev": "vite dev",
"dev": "nodemon -w ../../packages/core/dist --exec \"vite dev\"",
"build": "vite build"
},
"dependencies": {
"vue": "^3.2.47"
"vue": "^3.3.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.1.0",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"@vue/compiler-sfc": "^3.2.47",
"sass": "^1.59.3",
"@vitejs/plugin-vue": "^4.3.4",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"@vue/compiler-sfc": "^3.3.4",
"sass": "^1.68.0",
"vite-plugin-vue-inspector": "workspace:*"
}
}
Loading

0 comments on commit 34dfa21

Please sign in to comment.