Skip to content

Commit e1eca4d

Browse files
authored
fix: resolve directives in nested scopes (#1)
1 parent 1cdd1cf commit e1eca4d

File tree

4 files changed

+37
-13
lines changed

4 files changed

+37
-13
lines changed

packages/babel-plugin-jsx/README.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,24 +243,29 @@ h(A, {
243243
244244
#### custom directive
245245
246-
Recommended when using string arguments
247-
248246
```jsx
249247
const App = {
250-
directives: { custom: customDirective },
248+
directives: { custom: vCustom },
251249
setup() {
252-
return () => <a v-custom:arg={val} />;
250+
return () => <a v-custom={val} />;
253251
},
254252
};
255253
```
256254
255+
Directive names will resolve a variable matching `/v[A-Z]/` first, `options.directives` is only needed to prevent the import from being reported as unused.
256+
257+
Arguments and modifiers can be added as an array:
258+
257259
```jsx
258-
const App = {
259-
directives: { custom: customDirective },
260-
setup() {
261-
return () => <a v-custom={[val, 'arg', ['a', 'b']]} />;
262-
},
263-
};
260+
// same as v-custom:arg.a.b="val" in a .vue file
261+
<a v-custom={[val, 'arg', ['a', 'b']]} />
262+
```
263+
264+
Or arguments as part of the attribute name:
265+
266+
```jsx
267+
<a v-custom:arg={val} />
268+
<b v-custom:arg={[val, ['a', 'b']]} />
264269
```
265270
266271
### Slot

packages/babel-plugin-jsx/src/parseDirectives.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,13 @@ const resolveDirective = (
186186
}
187187
const referenceName =
188188
'v' + directiveName[0].toUpperCase() + directiveName.slice(1);
189-
if (path.scope.references[referenceName]) {
190-
return t.identifier(referenceName);
191-
}
189+
let scope = path.scope;
190+
do {
191+
if (scope.references[referenceName]) {
192+
return t.identifier(referenceName);
193+
}
194+
scope = scope.parent;
195+
} while (scope);
192196
return t.callExpression(createIdentifier(state, 'resolveDirective'), [
193197
t.stringLiteral(directiveName),
194198
]);

packages/babel-plugin-jsx/test/__snapshots__/snapshot.test.ts.snap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ _createVNode(_Fragment, null, [_withDirectives(_createVNode(_resolveComponent("A
6363
}]])]);"
6464
`;
6565
66+
exports[`directive in outer scope > directive in outer scope 1`] = `
67+
"import { resolveComponent as _resolveComponent, createVNode as _createVNode, withDirectives as _withDirectives } from "vue";
68+
const vXxx = {};
69+
() => _withDirectives(_createVNode(_resolveComponent("A"), null, null, 512), [[vXxx]]);"
70+
`;
71+
6672
exports[`directive in scope > directive in scope 1`] = `
6773
"import { resolveComponent as _resolveComponent, createVNode as _createVNode, withDirectives as _withDirectives } from "vue";
6874
const vXxx = {};

packages/babel-plugin-jsx/test/snapshot.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ const transpile = (source: string, options: VueJSXPluginOptions = {}) =>
162162
<A v-xxx />
163163
`,
164164
},
165+
{
166+
name: 'directive in outer scope',
167+
from: `
168+
const vXxx = {};
169+
() => (
170+
<A v-xxx />
171+
);
172+
`,
173+
},
165174
{
166175
name: 'vModels',
167176
from: '<C v-models={[[foo, ["modifier"]], [bar, "bar", ["modifier1", "modifier2"]]]} />',

0 commit comments

Comments
 (0)