diff --git a/package.json b/package.json
index ba3c2f3..87a4559 100644
--- a/package.json
+++ b/package.json
@@ -50,8 +50,9 @@
"@babel/traverse": "^7.16.3",
"@babel/types": "^7.16.0",
"@rollup/pluginutils": "^4.1.1",
- "@vue/ref-transform": "^3.2.21",
- "@vue/shared": "^3.2.21",
+ "@vue/compiler-core": "^3.2.23",
+ "@vue/ref-transform": "^3.2.23",
+ "@vue/shared": "^3.2.23",
"defu": "^5.0.0",
"htmlparser2": "5.0.1",
"magic-string": "^0.25.7",
@@ -63,7 +64,7 @@
"@types/jest": "^27.0.2",
"@types/node": "^16.11.7",
"@vue/composition-api": "^1.4.0",
- "@vue/runtime-dom": "^3.2.21",
+ "@vue/runtime-dom": "^3.2.23",
"bumpp": "^7.1.1",
"eslint": "^8.2.0",
"eslint-plugin-jest": "^25.2.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a55315b..d8802a8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,10 +15,11 @@ importers:
'@rollup/pluginutils': ^4.1.1
'@types/jest': ^27.0.2
'@types/node': ^16.11.7
+ '@vue/compiler-core': ^3.2.23
'@vue/composition-api': ^1.4.0
- '@vue/ref-transform': ^3.2.21
- '@vue/runtime-dom': ^3.2.21
- '@vue/shared': ^3.2.21
+ '@vue/ref-transform': ^3.2.23
+ '@vue/runtime-dom': ^3.2.23
+ '@vue/shared': ^3.2.23
bumpp: ^7.1.1
defu: ^5.0.0
eslint: ^8.2.0
@@ -44,8 +45,9 @@ importers:
'@babel/traverse': 7.16.3
'@babel/types': 7.16.0
'@rollup/pluginutils': 4.1.1
- '@vue/ref-transform': 3.2.21
- '@vue/shared': 3.2.21
+ '@vue/compiler-core': 3.2.23
+ '@vue/ref-transform': 3.2.23
+ '@vue/shared': 3.2.23
defu: 5.0.0
htmlparser2: 5.0.1
magic-string: 0.25.7
@@ -56,7 +58,7 @@ importers:
'@types/jest': 27.0.2
'@types/node': 16.11.7
'@vue/composition-api': 1.4.0
- '@vue/runtime-dom': 3.2.21
+ '@vue/runtime-dom': 3.2.23
bumpp: 7.1.1
eslint: 8.2.0
eslint-plugin-jest: 25.2.4_17df0fa4ec9ba9d0cf30cc54515c24df
@@ -3193,6 +3195,16 @@ packages:
'@vue/shared': 3.2.21
estree-walker: 2.0.2
source-map: 0.6.1
+ dev: true
+
+ /@vue/compiler-core/3.2.23:
+ resolution: {integrity: sha512-4ZhiI/orx+7EJ1B+0zjgvXMV2uRN+XBfG06UN2sJfND9rH5gtEQT3QmO4erum1o6Irl7y754W8/KSaDJh4EUQg==}
+ dependencies:
+ '@babel/parser': 7.16.3
+ '@vue/shared': 3.2.23
+ estree-walker: 2.0.2
+ source-map: 0.6.1
+ dev: false
/@vue/compiler-dom/3.2.21:
resolution: {integrity: sha512-gsJD3DpYZSYquiA7UIPsMDSlAooYWDvHPq9VRsqzJEk2PZtFvLvHPb4aaMD8Ufd62xzYn32cnnkzsEOJhyGilA==}
@@ -3249,6 +3261,12 @@ packages:
'@vue/shared': 3.2.21
dev: true
+ /@vue/reactivity/3.2.23:
+ resolution: {integrity: sha512-8RGVr/5Kpgb/EkCjgHXqttgA5IMc6n0lIXFY4TVbMkzdXrvaIhzBd7Te44oIDsTSYVKZLpfHd6/wEnuDqE8vFw==}
+ dependencies:
+ '@vue/shared': 3.2.23
+ dev: true
+
/@vue/ref-transform/3.2.21:
resolution: {integrity: sha512-uiEWWBsrGeun9O7dQExYWzXO3rHm/YdtFNXDVqCSoPypzOVxWxdiL+8hHeWzxMB58fVuV2sT80aUtIVyaBVZgQ==}
dependencies:
@@ -3257,6 +3275,17 @@ packages:
'@vue/shared': 3.2.21
estree-walker: 2.0.2
magic-string: 0.25.7
+ dev: true
+
+ /@vue/ref-transform/3.2.23:
+ resolution: {integrity: sha512-gW0GD2PSAs/th7mC7tPB/UwpIQxclbApVtsDtscDmOJXb2+cdu60ny+SuHNgfrlUT/JqWKQHq7jFKO4woxLNaA==}
+ dependencies:
+ '@babel/parser': 7.16.3
+ '@vue/compiler-core': 3.2.23
+ '@vue/shared': 3.2.23
+ estree-walker: 2.0.2
+ magic-string: 0.25.7
+ dev: false
/@vue/runtime-core/3.2.21:
resolution: {integrity: sha512-7oOxKaU0D2IunOAMOOHZgJVrHg63xwng8BZx3fbgmakqEIMwHhQcp+5GV1sOg/sWW7R4UhaRDIUCukO2GRVK2Q==}
@@ -3265,6 +3294,13 @@ packages:
'@vue/shared': 3.2.21
dev: true
+ /@vue/runtime-core/3.2.23:
+ resolution: {integrity: sha512-wSI5lmY2kCGLf89iiygqxVh6/5bsawz78Me9n1x4U2bHnN0yf3PWyuhN0WgIE8VfEaF7e75E333uboNEIFjgkg==}
+ dependencies:
+ '@vue/reactivity': 3.2.23
+ '@vue/shared': 3.2.23
+ dev: true
+
/@vue/runtime-dom/3.2.21:
resolution: {integrity: sha512-apBdriD6QsI4ywbllY8kjr9/0scGuStDuvLbJULPQkFPtHzntd51bP5PQTQVAEIc9kwnTozmj6x6ZdX/cwo7xA==}
dependencies:
@@ -3273,8 +3309,20 @@ packages:
csstype: 2.6.18
dev: true
+ /@vue/runtime-dom/3.2.23:
+ resolution: {integrity: sha512-z6lp0888NkLmxD9j2sGoll8Kb7J743s8s6w7GbiyUc4WZwm0KJ35B4qTFDMoIU0G7CatS6Z+yRTpPHc6srtByg==}
+ dependencies:
+ '@vue/runtime-core': 3.2.23
+ '@vue/shared': 3.2.23
+ csstype: 2.6.18
+ dev: true
+
/@vue/shared/3.2.21:
resolution: {integrity: sha512-5EQmIPK6gw4UVYUbM959B0uPsJ58+xoMESCZs3N89XyvJ9e+fX4pqEPrOGV8OroIk3SbEvJcC+eYc8BH9JQrHA==}
+ dev: true
+
+ /@vue/shared/3.2.23:
+ resolution: {integrity: sha512-U+/Jefa0QfXUF2qVy9Dqlrb6HKJSr9/wJcM66wXmWcTOoqg7hOWzF4qruDle51pyF4x3wMn6TSH54UdjKjCKMA==}
/@vue/web-component-wrapper/1.3.0:
resolution: {integrity: sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==}
diff --git a/src/core/parseSFC.ts b/src/core/parseSFC.ts
index ed539ce..ba6460c 100644
--- a/src/core/parseSFC.ts
+++ b/src/core/parseSFC.ts
@@ -1,5 +1,6 @@
import { Parser as HTMLParser, ParserOptions as HTMLParserOptions } from 'htmlparser2'
import type { ParserOptions } from '@babel/parser'
+import { NodeTypes, baseCompile } from '@vue/compiler-core'
import { camelize, isHTMLTag, isSVGTag, isVoidTag } from '@vue/shared'
import { ParsedSFC, ScriptSetupTransformOptions, ScriptTagMeta } from '../types'
import { getIdentifierUsages } from './identifiers'
@@ -31,6 +32,32 @@ const BUILD_IN_DIRECTIVES = new Set([
// 'ref',
])
+const parseDirective = (attr: string) => {
+ try {
+ const elementNode = baseCompile(``).ast.children[0]
+ if (elementNode?.type !== NodeTypes.ELEMENT) return undefined
+
+ const directiveNode = elementNode.props[0]
+ if (directiveNode?.type !== NodeTypes.DIRECTIVE) return undefined
+
+ const { arg, modifiers, name } = directiveNode
+ const argExpression
+ = arg?.type !== NodeTypes.SIMPLE_EXPRESSION
+ ? undefined
+ : arg.isStatic
+ ? JSON.stringify(arg.content)
+ : arg.content
+ return {
+ argExpression,
+ modifiers,
+ name,
+ }
+ }
+ catch (error) {
+ return undefined
+ }
+}
+
export function parseSFC(code: string, id?: string, options?: ScriptSetupTransformOptions): ParsedSFC {
/** foo-bar -> FooBar */
const components = new Set()
@@ -78,25 +105,30 @@ export function parseSFC(code: string, id?: string, options?: ScriptSetupTransfo
function handleTemplateContent(name: string, attributes: Record) {
if (!isHTMLTag(name) && !isSVGTag(name) && !isVoidTag(name))
- components.add(pascalize((name)))
+ components.add(pascalize(name))
Object.entries(attributes).forEach(([key, value]) => {
- if (!value)
+ // ref
+ if (key === 'ref') {
+ identifiers.add(value)
return
- if (key.startsWith('v-') || key.startsWith('@') || key.startsWith(':')) {
+ }
+
+ if (value !== '' && (key.startsWith('v-') || key.startsWith('@') || key.startsWith(':'))) {
if (key === 'v-for')
// we strip out delectations for v-for before `in` or `of`
expressions.add(`(${value.replace(/^.*\s(?:in|of)\s/, '')})`)
else
expressions.add(`(${value})`)
}
+
if (key.startsWith('v-')) {
- const directiveName = key.slice('v-'.length).split(':')[0].split('.')[0]
- if (!BUILD_IN_DIRECTIVES.has(directiveName))
- directives.add(camelize(directiveName))
+ const parsedDirective = parseDirective(key)
+ if (parsedDirective && !BUILD_IN_DIRECTIVES.has(parsedDirective.name))
+ directives.add(camelize(parsedDirective.name))
+ if (parsedDirective?.argExpression)
+ expressions.add(parsedDirective.argExpression)
}
- if (key === 'ref')
- identifiers.add(value)
})
}
diff --git a/test/__snapshots__/transform.test.ts.snap b/test/__snapshots__/transform.test.ts.snap
index 51e57a0..ba9fee6 100644
--- a/test/__snapshots__/transform.test.ts.snap
+++ b/test/__snapshots__/transform.test.ts.snap
@@ -183,7 +183,18 @@ export default __sfc_main;
exports[`transform fixtures test/fixtures/ComponentsDirectives.vue 1`] = `
"
-
+
@@ -191,17 +202,30 @@ exports[`transform fixtures test/fixtures/ComponentsDirectives.vue 1`] = `
diff --git a/test/fixtures/ComponentsDirectives.vue b/test/fixtures/ComponentsDirectives.vue
index 5aa9c97..30c78ad 100644
--- a/test/fixtures/ComponentsDirectives.vue
+++ b/test/fixtures/ComponentsDirectives.vue
@@ -1,6 +1,17 @@
-
+
@@ -8,9 +19,16 @@