Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd0d31ec

Browse files
zhiyuanzmjsxzz
andauthored
feat: addjsx-directive plugin (#430)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
1 parentd1c2f52 commitd0d31ec

33 files changed

+763
-0
lines changed

‎.changeset/brave-badgers-cheer.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@vue-macros/jsx-directive':minor
3+
'unplugin-vue-macros':minor
4+
---
5+
6+
add jsx-directive plugin

‎docs/.vitepress/locales/common.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ export const sidebar = (lang: string): DefaultTheme.SidebarItem[] => {
173173
text:'exportExpose',
174174
link:`${urlPrefix}/features/export-expose`,
175175
},
176+
{
177+
text:'jsxDirective',
178+
link:`${urlPrefix}/features/jsx-directive`,
179+
},
176180
],
177181
},
178182
],

‎docs/features/jsx-directive.md‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#jsxDirective
2+
3+
<StabilityLevellevel="experimental" />
4+
5+
`v-if` and`v-for` directive for jsx.
6+
7+
| Features| Supported|
8+
| :----------:| :----------------:|
9+
| Vue 3|:white_check_mark:|
10+
| Nuxt 3|:white_check_mark:|
11+
| Vue 2|:white_check_mark:|
12+
| Volar(v-for)|:x:|
13+
14+
##Usage
15+
16+
```vue
17+
<script setup lang="tsx">
18+
const { foo, list } = defineProps<{
19+
foo: number
20+
list: number[]
21+
}>()
22+
23+
defineRender(() => (
24+
<>
25+
<div v-if={foo === 0}>
26+
<div v-if={foo === 0}>0-0</div>
27+
<div v-else-if={foo === 1}>0-1</div>
28+
<div v-else>0-2</div>
29+
</div>
30+
31+
<div v-for={(i, index) in list} key={index}>
32+
{i}
33+
</div>
34+
</>
35+
))
36+
</script>
37+
```
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#jsxDirective
2+
3+
<StabilityLevellevel="experimental" />
4+
5+
`v-if` and`v-for` directive for jsx.
6+
7+
| Features| Supported|
8+
| :----------:| :----------------:|
9+
| Vue 3|:white_check_mark:|
10+
| Nuxt 3|:white_check_mark:|
11+
| Vue 2|:white_check_mark:|
12+
| Volar(v-for)|:x:|
13+
14+
##Usage
15+
16+
```vue
17+
<script setup lang="tsx">
18+
const { foo, list } = defineProps<{
19+
foo: number
20+
list: number[]
21+
}>()
22+
23+
defineRender(() => (
24+
<>
25+
<div v-if={foo === 0}>
26+
<div v-if={foo === 0}>0-0</div>
27+
<div v-else-if={foo === 1}>0-1</div>
28+
<div v-else>0-2</div>
29+
</div>
30+
31+
<div v-for={(i, index) in list} key={index}>
32+
{i}
33+
</div>
34+
</>
35+
))
36+
</script>
37+
```

‎packages/jsx-directive/README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#@vue-macros/jsx-directive[![npm](https://img.shields.io/npm/v/@vue-macros/jsx-directive.svg)](https://npmjs.com/package/@vue-macros/jsx-directive)
2+
3+
Please refer to[README.md](https://github.com/sxzz/vue-macros#readme)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"name":"@vue-macros/jsx-directive",
3+
"version":"0.0.0",
4+
"packageManager":"pnpm@8.6.7",
5+
"description":"jsx-directive feature from Vue Macros.",
6+
"keywords": [
7+
"vue-macros",
8+
"macros",
9+
"vue",
10+
"sfc",
11+
"setup",
12+
"script-setup",
13+
"jsx-directive",
14+
"unplugin"
15+
],
16+
"license":"MIT",
17+
"homepage":"https://github.com/sxzz/vue-macros#readme",
18+
"bugs": {
19+
"url":"https://github.com/sxzz/vue-macros/issues"
20+
},
21+
"repository": {
22+
"type":"git",
23+
"url":"git+https://github.com/sxzz/vue-macros.git",
24+
"directory":"packages/jsx-directive"
25+
},
26+
"author":"zhiyuanzmj",
27+
"contributors": [
28+
"三咲智子 <sxzz@sxzz.moe>"
29+
],
30+
"files": [
31+
"dist"
32+
],
33+
"main":"dist/index.js",
34+
"module":"dist/index.mjs",
35+
"types":"dist/index.d.ts",
36+
"exports": {
37+
".": {
38+
"dev":"./src/index.ts",
39+
"types": {
40+
"require":"./dist/index.d.ts",
41+
"import":"./dist/index.d.mts"
42+
},
43+
"require":"./dist/index.js",
44+
"import":"./dist/index.mjs"
45+
},
46+
"./api": {
47+
"dev":"./src/api.ts",
48+
"types": {
49+
"require":"./dist/api.d.ts",
50+
"import":"./dist/api.d.mts"
51+
},
52+
"require":"./dist/api.js",
53+
"import":"./dist/api.mjs"
54+
},
55+
"./esbuild": {
56+
"dev":"./src/esbuild.ts",
57+
"types": {
58+
"require":"./dist/esbuild.d.ts",
59+
"import":"./dist/esbuild.d.mts"
60+
},
61+
"require":"./dist/esbuild.js",
62+
"import":"./dist/esbuild.mjs"
63+
},
64+
"./rollup": {
65+
"dev":"./src/rollup.ts",
66+
"types": {
67+
"require":"./dist/rollup.d.ts",
68+
"import":"./dist/rollup.d.mts"
69+
},
70+
"require":"./dist/rollup.js",
71+
"import":"./dist/rollup.mjs"
72+
},
73+
"./vite": {
74+
"dev":"./src/vite.ts",
75+
"types": {
76+
"require":"./dist/vite.d.ts",
77+
"import":"./dist/vite.d.mts"
78+
},
79+
"require":"./dist/vite.js",
80+
"import":"./dist/vite.mjs"
81+
},
82+
"./webpack": {
83+
"dev":"./src/webpack.ts",
84+
"types": {
85+
"require":"./dist/webpack.d.ts",
86+
"import":"./dist/webpack.d.mts"
87+
},
88+
"require":"./dist/webpack.js",
89+
"import":"./dist/webpack.mjs"
90+
},
91+
"./*": [
92+
"./*",
93+
"./*.d.ts"
94+
]
95+
},
96+
"typesVersions": {
97+
"*": {
98+
"*": [
99+
"./dist/*",
100+
"./*"
101+
]
102+
}
103+
},
104+
"scripts": {
105+
"build":"tsup && tsx ../../scripts/postbuild.ts",
106+
"dev":"DEV=true tsup"
107+
},
108+
"dependencies": {
109+
"@vue-macros/common":"workspace:~",
110+
"unplugin":"^1.3.1"
111+
},
112+
"devDependencies": {
113+
"vue":"^3.3.4"
114+
},
115+
"engines": {
116+
"node":">=16.14.0"
117+
}
118+
}

‎packages/jsx-directive/src/api.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export*from'./core'
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import{typeProgram}from'@babel/types'
2+
import{
3+
MagicString,
4+
babelParse,
5+
getLang,
6+
getTransformResult,
7+
parseSFC,
8+
}from'@vue-macros/common'
9+
import{vIfTransform}from'./v-if'
10+
import{vForTransform}from'./v-for'
11+
12+
exportfunctiontransformJsxVueDirective(code:string,id:string){
13+
constlang=getLang(id)
14+
letasts:{
15+
ast:Program
16+
offset:number
17+
}[]=[]
18+
if(lang==='vue'){
19+
const{ scriptSetup, getSetupAst, script, getScriptAst}=parseSFC(
20+
code,
21+
id
22+
)
23+
if(script){
24+
asts.push({ast:getScriptAst()!,offset:script.loc.start.offset})
25+
}
26+
if(scriptSetup){
27+
asts.push({ast:getSetupAst()!,offset:scriptSetup.loc.start.offset})
28+
}
29+
}elseif(['jsx','tsx'].includes(lang)){
30+
asts=[{ast:babelParse(code,lang),offset:0}]
31+
}else{
32+
return
33+
}
34+
35+
consts=newMagicString(code)
36+
for(const{ ast, offset}ofasts){
37+
vIfTransform(ast,s,offset)
38+
vForTransform(ast,s,offset)
39+
}
40+
41+
returngetTransformResult(s,id)
42+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import{
2+
typeJSXAttribute,
3+
typeJSXElement,
4+
typeNode,
5+
typeProgram,
6+
}from'@babel/types'
7+
import{typeMagicString,walkAST}from'@vue-macros/common'
8+
9+
exportfunctionvForTransform(ast:Program,s:MagicString,offset=0){
10+
if(!s.sliceNode(ast,{ offset}).includes('v-for'))return
11+
12+
constnodes:{
13+
node:JSXElement
14+
attribute:JSXAttribute
15+
}[]=[]
16+
17+
walkAST<Node>(ast,{
18+
enter(node){
19+
if(node.type!=='JSXElement')return
20+
21+
constattribute=node.openingElement.attributes.find(
22+
(i):i isJSXAttribute=>
23+
i.type==='JSXAttribute'&&['v-for'].includes(`${i.name.name}`)
24+
)
25+
if(attribute){
26+
nodes.push({
27+
node,
28+
attribute,
29+
})
30+
}
31+
},
32+
})
33+
34+
nodes.forEach(({ node, attribute})=>{
35+
if(`${attribute.name.name}`==='v-for'){
36+
if(!attribute.value)return
37+
const[i,list]=s
38+
.slice(
39+
attribute.value.start!+offset+1,
40+
attribute.value.end!+offset-1
41+
)
42+
.split(/\s+in\s+/)
43+
44+
s.appendLeft(node.start!+offset,` {${list}.map(${i}=> `)
45+
46+
s.appendRight(node.end!+offset,') }')
47+
s.remove(attribute.start!+offset-1,attribute.end!+offset)
48+
}
49+
})
50+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import{
2+
typeJSXAttribute,
3+
typeJSXElement,
4+
typeNode,
5+
typeProgram,
6+
}from'@babel/types'
7+
import{typeMagicString,walkAST}from'@vue-macros/common'
8+
9+
exportfunctionvIfTransform(ast:Program,s:MagicString,offset=0){
10+
if(!s.sliceNode(ast,{ offset}).includes('v-if'))return
11+
12+
constnodeMap=newMap<
13+
Node,
14+
{
15+
node:JSXElement
16+
attribute:JSXAttribute
17+
}[]
18+
>()
19+
20+
walkAST<Node>(ast,{
21+
enter(node,parent){
22+
if(node.type!=='JSXElement')return
23+
24+
constattribute=node.openingElement.attributes.find(
25+
(i)=>
26+
i.type==='JSXAttribute'&&
27+
['v-if','v-else-if','v-else'].includes(`${i.name.name}`)
28+
)asJSXAttribute
29+
if(attribute){
30+
if(!nodeMap.has(parent!))nodeMap.set(parent!,[])
31+
32+
nodeMap.get(parent!)?.push({
33+
node,
34+
attribute,
35+
})
36+
}
37+
},
38+
})
39+
40+
constnodes=[...nodeMap.values()].flat()
41+
nodes.forEach(({ node, attribute},index)=>{
42+
if(['v-if','v-else-if'].includes(`${attribute.name.name}`)){
43+
if(attribute.value)
44+
s.appendLeft(
45+
node.start!+offset,
46+
`${attribute.name.name==='v-if' ?'{ ' :''}${s.slice(
47+
attribute.value.start!+offset+1,
48+
attribute.value.end!+offset-1
49+
)} ? `
50+
)
51+
52+
s.appendRight(
53+
node.end!+offset,
54+
`${nodes[index+1]?.attribute.name.name}`.startsWith('v-else')
55+
?' :'
56+
:" : '' }"
57+
)
58+
s.remove(attribute.start!+offset-1,attribute.end!+offset)
59+
}else{
60+
s.appendRight(node.end!+offset,' }')
61+
}
62+
})
63+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp