fix: evaluate __can__ before branch conditions
This commit is contained in:
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.1.1] - 2025-11-15
|
||||
### Changed
|
||||
- Evaluate `__can__` guards before business expressions when merging into `v-if` / `v-else-if` branches to keep short-circuit order predictable.
|
||||
|
||||
## [1.1.0] - 2025-11-15
|
||||
### Added
|
||||
- Automatically mirror `v-can` guards across `v-else-if` / `v-else` branches and surface the inferred expression in documentation and fixtures.
|
||||
@@ -35,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- English README describing usage, playground, and contribution guide.
|
||||
- Roadmap and release prep guidance.
|
||||
|
||||
[1.1.1]: https://github.com/eduvia-app/nuxt-can/releases/tag/v1.1.1
|
||||
[1.1.0]: https://github.com/eduvia-app/nuxt-can/releases/tag/v1.1.0
|
||||
[1.0.1]: https://github.com/eduvia-app/nuxt-can/releases/tag/v1.0.1
|
||||
[1.0.0]: https://github.com/eduvia-app/nuxt-can/releases/tag/v1.0.0
|
||||
|
||||
@@ -73,7 +73,7 @@ Now you can write directives that stay type-safe:
|
||||
|
||||
```vue
|
||||
<button v-if="__can__('employee', 'view')">View profile</button>
|
||||
<button v-if="(isReady) && __can__('employee', 'edit')">Edit profile</button>
|
||||
<button v-if="__can__('employee', 'edit') && (isReady)">Edit profile</button>
|
||||
<p v-if="!(__can__('employee', 'edit'))">Access denied</p>
|
||||
```
|
||||
|
||||
@@ -101,10 +101,10 @@ Once the first branch of a conditional chain carries `v-can`, the transformer au
|
||||
Transforms into:
|
||||
|
||||
```vue
|
||||
<div v-if="(status === 'draft') && __can__('foo', 'bar')">
|
||||
<div v-if="__can__('foo', 'bar') && (status === 'draft')">
|
||||
Draft state
|
||||
</div>
|
||||
<div v-else-if="(status === 'pending') && __can__('foo', 'bar')">
|
||||
<div v-else-if="__can__('foo', 'bar') && (status === 'pending')">
|
||||
Pending state
|
||||
</div>
|
||||
<div v-else-if="__can__('foo', 'bar')">
|
||||
|
||||
@@ -59,7 +59,7 @@ Ce document sert de guide de travail pour construire le plugin Nuxt et son trans
|
||||
### 🚀 Phase 4 — Transformation des nœuds `v-can`
|
||||
- Convertir l’expression en chemin `['segment1','segment2',…]`.
|
||||
- Chercher un `v-if` existant :
|
||||
- `v-if="expr"` → `v-if="(expr) && __can__(path)"`.
|
||||
- `v-if="expr"` → `v-if="__can__(path) && (expr)"`.
|
||||
- Sans `v-if` → ajouter `v-if="__can__(path)"`.
|
||||
- Interdire `v-can` sur des éléments possédant déjà `v-else` / `v-else-if` (lever une erreur compilateur).
|
||||
|
||||
@@ -125,7 +125,7 @@ Avant :
|
||||
Après compilation :
|
||||
|
||||
```vue
|
||||
<div v-if="(isReady) && __can__('contract', 'edit')">
|
||||
<div v-if="__can__('contract', 'edit') && (isReady)">
|
||||
Modifier le contrat
|
||||
</div>
|
||||
```
|
||||
@@ -141,7 +141,7 @@ Avant :
|
||||
Après compilation :
|
||||
|
||||
```vue
|
||||
<button v-if="(ctaVisible) && __can__('employee', 'view')">Voir</button>
|
||||
<button v-if="__can__('employee', 'view') && (ctaVisible)">Voir</button>
|
||||
<p v-if="!__can__('employee', 'view')">Acces refuse</p>
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@eduvia-app/nuxt-can",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"description": "Nuxt directives (`v-can`, `v-cannot`) to layer permissions without touching business v-ifs.",
|
||||
"author": "Eduvia <engineering@eduvia.app>",
|
||||
"homepage": "https://github.com/eduvia-app/nuxt-can#readme",
|
||||
|
||||
@@ -317,7 +317,7 @@ function mergeGuardIntoConditional(params: {
|
||||
ctx.patches.push({
|
||||
start: ctx.templateStart + conditionDirective.loc.start.offset,
|
||||
end: ctx.templateStart + conditionDirective.loc.end.offset,
|
||||
text: `v-if="(${conditionExpression}) && ${canInvocation}"`,
|
||||
text: `v-if="${canInvocation} && (${conditionExpression})"`,
|
||||
})
|
||||
|
||||
return
|
||||
@@ -333,7 +333,7 @@ function mergeGuardIntoConditional(params: {
|
||||
ctx.patches.push({
|
||||
start: ctx.templateStart + conditionDirective.loc.start.offset,
|
||||
end: ctx.templateStart + conditionDirective.loc.end.offset,
|
||||
text: `v-else-if="(${conditionExpression}) && ${canInvocation}"`,
|
||||
text: `v-else-if="${canInvocation} && (${conditionExpression})"`,
|
||||
})
|
||||
|
||||
return
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('transformCan', () => {
|
||||
<div v-if="isReady" v-can="can.contract.create" />
|
||||
`)
|
||||
|
||||
expect(code).toContain(`v-if="(isReady) && __can__('contract', 'create')"`)
|
||||
expect(code).toContain(`v-if="__can__('contract', 'create') && (isReady)"`)
|
||||
})
|
||||
|
||||
it('throws when v-cannot is used without a preceding v-can', () => {
|
||||
@@ -56,8 +56,8 @@ describe('transformCan', () => {
|
||||
<p v-cannot>Denied</p>
|
||||
`)
|
||||
|
||||
expect(code).toContain(`v-if="(ready) && __can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-else-if="(later) && __can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-if="__can__('employee', 'view') && (ready)"`)
|
||||
expect(code).toContain(`v-else-if="__can__('employee', 'view') && (later)"`)
|
||||
expect(code).toContain(`v-else-if="__can__('employee', 'view')"`)
|
||||
expect(code).toContain(`v-if="!(__can__('employee', 'view'))"`)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user