Skip to content

Commit 4710c81

Browse files
committed
feat: add booleanProp feature
1 parent 301a004 commit 4710c81

File tree

21 files changed

+429
-12
lines changed

21 files changed

+429
-12
lines changed

.changeset/gorgeous-ads-marry.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@vue-macros/boolean-prop': minor
3+
'@vue-macros/nuxt': minor
4+
---
5+
6+
add booleanProp feature

docs/.vitepress/locales/common.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ export const sidebar = (lang: string): DefaultTheme.SidebarItem[] => {
179179
text: 'jsxDirective',
180180
link: `${urlPrefix}/features/jsx-directive`,
181181
},
182+
{
183+
text: 'booleanProp',
184+
link: `${urlPrefix}/features/boolean-prop`,
185+
},
182186
],
183187
},
184188
],

docs/features/boolean-prop.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# booleanProp
2+
3+
<StabilityLevel level="stable" />
4+
5+
Convert `<Comp checked />` to `<Comp :checked="true" />`.
6+
7+
| Features | Supported |
8+
| :----------: | :----------------: |
9+
| Vue 3 | :white_check_mark: |
10+
| Nuxt 3 | :white_check_mark: |
11+
| Vue 2 | :x: |
12+
| Volar Plugin | :white_check_mark: |
13+
14+
## Setup
15+
16+
### Installation
17+
18+
```bash
19+
npm i @vue-macros/boolean-prop
20+
```
21+
22+
### Vite Integration
23+
24+
```ts {9-13}
25+
// vite.config.ts
26+
import { defineConfig } from 'vite'
27+
import Vue from '@vitejs/plugin-vue'
28+
import { transformBooleanProp } from '@vue-macros/boolean-prop'
29+
30+
export default defineConfig({
31+
plugins: [
32+
Vue({
33+
template: {
34+
compilerOptions: {
35+
nodeTransforms: [transformBooleanProp()],
36+
},
37+
},
38+
}),
39+
],
40+
})
41+
```
42+
43+
## Usage
44+
45+
```vue
46+
<template>
47+
<Comp checked />
48+
</template>
49+
```
50+
51+
```vue
52+
<script setup lang="ts">
53+
// Comp.vue
54+
defineProps<{
55+
checked?: any
56+
}>()
57+
</script>
58+
```
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# booleanProp
2+
3+
<StabilityLevel level="stable" />
4+
5+
Convert `<Comp checked />` to `<Comp :checked="true" />`.
6+
7+
| Features | Supported |
8+
| :----------: | :----------------: |
9+
| Vue 3 | :white_check_mark: |
10+
| Nuxt 3 | :white_check_mark: |
11+
| Vue 2 | :x: |
12+
| Volar Plugin | :white_check_mark: |
13+
14+
## Setup
15+
16+
### Installation
17+
18+
```bash
19+
npm i @vue-macros/boolean-prop
20+
```
21+
22+
### Vite Integration
23+
24+
```ts {9-13}
25+
// vite.config.ts
26+
import { defineConfig } from 'vite'
27+
import Vue from '@vitejs/plugin-vue'
28+
import { transformBooleanProp } from '@vue-macros/boolean-prop'
29+
30+
export default defineConfig({
31+
plugins: [
32+
Vue({
33+
template: {
34+
compilerOptions: {
35+
nodeTransforms: [transformBooleanProp()],
36+
},
37+
},
38+
}),
39+
],
40+
})
41+
```
42+
43+
## Usage
44+
45+
```vue
46+
<template>
47+
<Comp checked />
48+
</template>
49+
```
50+
51+
```vue
52+
<script setup lang="ts">
53+
// Comp.vue
54+
defineProps<{
55+
checked?: any
56+
}>()
57+
</script>
58+
```

packages/boolean-prop/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# @vue-macros/boolean-prop [![npm](https://img.shields.io/npm/v/@vue-macros/boolean-prop.svg)](https://npmjs.com/package/@vue-macros/boolean-prop)
2+
3+
Please refer to [README.md](https://github.com/vue-macros/vue-macros#readme)

packages/boolean-prop/package.json

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"name": "@vue-macros/boolean-prop",
3+
"version": "0.0.0",
4+
"packageManager": "pnpm@8.6.11",
5+
"description": "boolean-prop feature from Vue Macros.",
6+
"keywords": [
7+
"vue-macros",
8+
"macros",
9+
"vue",
10+
"sfc",
11+
"setup",
12+
"script-setup",
13+
"boolean-prop"
14+
],
15+
"license": "MIT",
16+
"homepage": "https://github.com/vue-macros/vue-macros#readme",
17+
"bugs": {
18+
"url": "https://github.com/vue-macros/vue-macros/issues"
19+
},
20+
"repository": {
21+
"type": "git",
22+
"url": "git+https://github.com/vue-macros/vue-macros.git",
23+
"directory": "packages/boolean-prop"
24+
},
25+
"author": "三咲智子 <sxzz@sxzz.moe>",
26+
"files": [
27+
"dist"
28+
],
29+
"main": "dist/index.js",
30+
"module": "dist/index.mjs",
31+
"types": "dist/index.d.ts",
32+
"exports": {
33+
".": {
34+
"dev": "./src/index.ts",
35+
"types": {
36+
"require": "./dist/index.d.ts",
37+
"import": "./dist/index.d.mts"
38+
},
39+
"require": "./dist/index.js",
40+
"import": "./dist/index.mjs"
41+
},
42+
"./*": [
43+
"./*",
44+
"./*.d.ts"
45+
]
46+
},
47+
"scripts": {
48+
"build": "tsup",
49+
"dev": "DEV=true tsup"
50+
},
51+
"dependencies": {
52+
"@vue-macros/common": "workspace:*",
53+
"@vue/compiler-core": "^3.3.4"
54+
},
55+
"devDependencies": {
56+
"@vue/compiler-sfc": "^3.3.4"
57+
},
58+
"engines": {
59+
"node": ">=16.14.0"
60+
}
61+
}

packages/boolean-prop/src/index.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {
2+
type ConstantTypes,
3+
type NodeTransform,
4+
type NodeTypes,
5+
} from '@vue/compiler-core'
6+
7+
export function transformBooleanProp(): NodeTransform {
8+
return (node) => {
9+
if (node.type !== (1 satisfies NodeTypes.ELEMENT)) return
10+
for (const [i, prop] of node.props.entries()) {
11+
if (
12+
prop.type !== (6 satisfies NodeTypes.ATTRIBUTE) ||
13+
prop.value !== undefined
14+
)
15+
continue
16+
node.props[i] = {
17+
type: 7 satisfies NodeTypes.DIRECTIVE,
18+
name: 'bind',
19+
arg: {
20+
type: 4 satisfies NodeTypes.SIMPLE_EXPRESSION,
21+
constType: 3 satisfies ConstantTypes.CAN_STRINGIFY,
22+
content: 'checked',
23+
isStatic: true,
24+
loc: prop.loc,
25+
},
26+
exp: {
27+
type: 4 satisfies NodeTypes.SIMPLE_EXPRESSION,
28+
constType: 3 satisfies ConstantTypes.CAN_STRINGIFY,
29+
content: 'true',
30+
isStatic: false,
31+
loc: prop.loc,
32+
},
33+
loc: prop.loc,
34+
modifiers: [],
35+
}
36+
}
37+
}
38+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`compiler > basic 1`] = `
4+
{
5+
"arg": {
6+
"constType": 3,
7+
"content": "checked",
8+
"isStatic": true,
9+
"loc": {
10+
"end": {
11+
"column": 13,
12+
"line": 1,
13+
"offset": 12,
14+
},
15+
"source": "check",
16+
"start": {
17+
"column": 8,
18+
"line": 1,
19+
"offset": 7,
20+
},
21+
},
22+
"type": 4,
23+
},
24+
"exp": {
25+
"constType": 3,
26+
"content": "true",
27+
"isStatic": false,
28+
"loc": {
29+
"end": {
30+
"column": 13,
31+
"line": 1,
32+
"offset": 12,
33+
},
34+
"source": "check",
35+
"start": {
36+
"column": 8,
37+
"line": 1,
38+
"offset": 7,
39+
},
40+
},
41+
"type": 4,
42+
},
43+
"loc": {
44+
"end": {
45+
"column": 13,
46+
"line": 1,
47+
"offset": 12,
48+
},
49+
"source": "check",
50+
"start": {
51+
"column": 8,
52+
"line": 1,
53+
"offset": 7,
54+
},
55+
},
56+
"modifiers": [],
57+
"name": "bind",
58+
"type": 7,
59+
}
60+
`;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`fixtures > tests/fixtures/basic.vue 1`] = `
4+
"import { openBlock, createElementBlock } from 'vue';
5+
import _export_sfc from '[NULL]/plugin-vue/export-helper';
6+
7+
const _sfc_main = {};
8+
9+
const _hoisted_1 = { checked: true };
10+
11+
function _sfc_render(_ctx, _cache) {
12+
return (openBlock(), createElementBlock(\\"input\\", _hoisted_1))
13+
}
14+
var basic = /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render],__FILE__]);
15+
16+
export { basic as default };
17+
"
18+
`;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { compileTemplate } from '@vue/compiler-sfc'
2+
import { describe, expect, test } from 'vitest'
3+
import { transformBooleanProp } from '../src'
4+
5+
function compile(code: string) {
6+
return compileTemplate({
7+
source: code,
8+
filename: 'anonymous.vue',
9+
id: 'xxx',
10+
compilerOptions: {
11+
nodeTransforms: [transformBooleanProp()],
12+
},
13+
})
14+
}
15+
16+
describe('compiler', () => {
17+
test('basic', () => {
18+
const original = compile(`<input :checked="true" />`)
19+
const sugar = compile(`<input check />`)
20+
expect(sugar.code).toBe(original.code)
21+
expect((sugar.ast as any).children[0].props[0]).matchSnapshot()
22+
})
23+
})

0 commit comments

Comments
 (0)