Skip to content

Commit 24081e3

Browse files
committed
feat!: add macros
1 parent a93b1e0 commit 24081e3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3322
-181
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"tsup": "^8.1.0",
4747
"typescript": "^5.7.0",
4848
"unplugin": "^1.11.0",
49+
"unplugin-raw": "^0.3.1",
4950
"vitest": "^1.6.0"
5051
},
5152
"pnpm": {

packages/babel/tsup.config.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
import process from 'node:process'
2-
import type { Options } from 'tsup'
1+
import { config } from '../../tsup.config.js'
32

4-
export default {
5-
entry: ['./src/index.ts'],
6-
clean: true,
7-
format: ['cjs', 'esm'],
8-
watch: !!process.env.DEV,
9-
dts: !process.env.DEV,
10-
cjsInterop: true,
11-
splitting: true,
12-
} satisfies Options
3+
export default config()

packages/compiler/tsup.config.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
import process from 'node:process'
2-
import type { Options } from 'tsup'
1+
import { config } from '../../tsup.config.js'
32

4-
export default {
5-
entry: ['./src/index.ts'],
6-
clean: true,
7-
format: ['cjs', 'esm'],
8-
watch: !!process.env.DEV,
9-
dts: !process.env.DEV,
10-
cjsInterop: true,
11-
splitting: true,
12-
define: {
13-
__DEV__: 'true',
14-
},
15-
} satisfies Options
3+
export default config({
4+
entry: ['src/index.ts'],
5+
})

packages/macros/package.json

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
{
2+
"name": "@vue-jsx-vapor/macros",
3+
"version": "1.6.0",
4+
"packageManager": "[email protected]",
5+
"description": "Macros for Vue JSX Vapor",
6+
"type": "module",
7+
"keywords": [
8+
"transform",
9+
"vue-jsx",
10+
"macros",
11+
"volar",
12+
"vapor"
13+
],
14+
"license": "MIT",
15+
"homepage": "https://github.com/unplugin/unplugin-vue-jsx-vapor#readme",
16+
"bugs": {
17+
"url": "https://github.com/unplugin/unplugin-vue-jsx-vapor/issues"
18+
},
19+
"repository": {
20+
"type": "git",
21+
"url": "git+https://github.com/unplugin/unplugin-vue-jsx-vapor.git"
22+
},
23+
"files": [
24+
"dist"
25+
],
26+
"main": "dist/index.cjs",
27+
"module": "dist/index.js",
28+
"types": "dist/index.d.ts",
29+
"exports": {
30+
".": {
31+
"dev": "./src/index.ts",
32+
"require": "./dist/index.cjs",
33+
"import": "./dist/index.js"
34+
},
35+
"./astro": {
36+
"require": "./dist/astro.cjs",
37+
"import": "./dist/astro.js"
38+
},
39+
"./rspack": {
40+
"require": "./dist/rspack.cjs",
41+
"import": "./dist/rspack.js"
42+
},
43+
"./vite": {
44+
"require": "./dist/vite.cjs",
45+
"import": "./dist/vite.js"
46+
},
47+
"./webpack": {
48+
"require": "./dist/webpack.cjs",
49+
"import": "./dist/webpack.js"
50+
},
51+
"./rollup": {
52+
"require": "./dist/rollup.cjs",
53+
"import": "./dist/rollup.js"
54+
},
55+
"./esbuild": {
56+
"require": "./dist/esbuild.cjs",
57+
"import": "./dist/esbuild.js"
58+
},
59+
"./nuxt": {
60+
"require": "./dist/nuxt.cjs",
61+
"import": "./dist/nuxt.js"
62+
},
63+
"./api": {
64+
"require": "./dist/api.cjs",
65+
"import": "./dist/api.js"
66+
},
67+
"./raw": {
68+
"require": "./dist/raw.cjs",
69+
"import": "./dist/raw.js"
70+
},
71+
"./volar": {
72+
"dev": "./src/volar.ts",
73+
"require": "./dist/volar.cjs",
74+
"import": "./dist/volar.js"
75+
},
76+
"./*": "./*"
77+
},
78+
"typesVersions": {
79+
"*": {
80+
"*": [
81+
"./dist/*",
82+
"./*"
83+
]
84+
}
85+
},
86+
"publishConfig": {
87+
".": {
88+
"require": "./dist/index.cjs",
89+
"import": "./dist/index.js"
90+
},
91+
"./astro": {
92+
"require": "./dist/astro.cjs",
93+
"import": "./dist/astro.js"
94+
},
95+
"./rspack": {
96+
"require": "./dist/rspack.cjs",
97+
"import": "./dist/rspack.js"
98+
},
99+
"./vite": {
100+
"require": "./dist/vite.cjs",
101+
"import": "./dist/vite.js"
102+
},
103+
"./webpack": {
104+
"require": "./dist/webpack.cjs",
105+
"import": "./dist/webpack.js"
106+
},
107+
"./rollup": {
108+
"require": "./dist/rollup.cjs",
109+
"import": "./dist/rollup.js"
110+
},
111+
"./esbuild": {
112+
"require": "./dist/esbuild.cjs",
113+
"import": "./dist/esbuild.js"
114+
},
115+
"./nuxt": {
116+
"require": "./dist/nuxt.cjs",
117+
"import": "./dist/nuxt.js"
118+
},
119+
"./api": {
120+
"require": "./dist/api.cjs",
121+
"import": "./dist/api.js"
122+
},
123+
"./raw": {
124+
"require": "./dist/raw.cjs",
125+
"import": "./dist/raw.js"
126+
},
127+
"./volar": {
128+
"require": "./dist/volar.cjs",
129+
"import": "./dist/volar.js"
130+
},
131+
"./*": "./*"
132+
},
133+
"scripts": {
134+
"build": "tsup",
135+
"dev": "DEV=true tsup"
136+
},
137+
"peerDependenciesMeta": {
138+
"@nuxt/kit": {
139+
"optional": true
140+
},
141+
"@nuxt/schema": {
142+
"optional": true
143+
},
144+
"esbuild": {
145+
"optional": true
146+
},
147+
"rollup": {
148+
"optional": true
149+
},
150+
"vite": {
151+
"optional": true
152+
},
153+
"webpack": {
154+
"optional": true
155+
}
156+
},
157+
"dependencies": {
158+
"@vue-macros/common": "3.0.0-beta.4",
159+
"@vue/compiler-sfc": "catalog:",
160+
"hash-sum": "^2.0.0",
161+
"ts-macro": "catalog:"
162+
},
163+
"devDependencies": {
164+
"@babel/types": "7.26.9",
165+
"@nuxt/kit": "^3.12.3",
166+
"@nuxt/schema": "^3.12.3",
167+
"@types/hash-sum": "^1.0.2",
168+
"@vue-macros/test-utils": "3.0.0-beta.4",
169+
"vue": "catalog:"
170+
}
171+
}

packages/macros/src/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './core'

packages/macros/src/astro.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import unplugin from '.'
2+
import type { Options } from './types'
3+
4+
export default (options: Options) => ({
5+
name: 'unplugin-vue-jsx-vapor',
6+
hooks: {
7+
'astro:config:setup': (astro: any) => {
8+
astro.config.vite.plugins ||= []
9+
astro.config.vite.plugins.push(unplugin.vite(options))
10+
},
11+
},
12+
})
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Modified from: https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/topLevelAwait.ts
2+
3+
import {
4+
type MagicStringAST,
5+
importHelperFn,
6+
walkAST,
7+
} from '@vue-macros/common'
8+
import type { FunctionalNode } from '..'
9+
import type { AwaitExpression, Function, Node, Statement } from '@babel/types'
10+
11+
// Copied from @vue/compiler-core
12+
export const isFunctionType = (node: Node): node is Function => {
13+
return /Function(?:Expression|Declaration)$|Method$/.test(node.type)
14+
}
15+
16+
export function transformAwait(root: FunctionalNode, s: MagicStringAST): void {
17+
if (root.body.type !== 'BlockStatement') return
18+
let hasAwait = false
19+
for (const node of root.body.body) {
20+
if (
21+
(node.type === 'VariableDeclaration' && !node.declare) ||
22+
node.type.endsWith('Statement')
23+
) {
24+
const scope: Statement[][] = [root.body.body]
25+
walkAST<Node>(node, {
26+
enter(child, parent) {
27+
if (isFunctionType(child)) {
28+
this.skip()
29+
}
30+
if (child.type === 'BlockStatement') {
31+
scope.push(child.body)
32+
}
33+
if (child.type === 'AwaitExpression') {
34+
hasAwait = true
35+
// if the await expression is an expression statement and
36+
// - is in the root scope
37+
// - or is not the first statement in a nested block scope
38+
// then it needs a semicolon before the generated code.
39+
const currentScope = scope.at(-1)
40+
const needsSemi = !!currentScope?.some((n, i) => {
41+
return (
42+
(scope.length === 1 || i > 0) &&
43+
n.type === 'ExpressionStatement' &&
44+
n.start === child.start
45+
)
46+
})
47+
processAwait(
48+
s,
49+
child,
50+
needsSemi,
51+
parent!.type === 'ExpressionStatement',
52+
)
53+
}
54+
},
55+
leave(node: Node) {
56+
if (node.type === 'BlockStatement') scope.pop()
57+
},
58+
})
59+
}
60+
}
61+
62+
if (hasAwait) {
63+
s.prependLeft(root.body.start! + 1, `\nlet __temp, __restore\n`)
64+
}
65+
}
66+
67+
function processAwait(
68+
s: MagicStringAST,
69+
node: AwaitExpression,
70+
needSemi: boolean,
71+
isStatement: boolean,
72+
): void {
73+
const argumentStart =
74+
node.argument.extra && node.argument.extra.parenthesized
75+
? (node.argument.extra.parenStart as number)
76+
: node.argument.start!
77+
78+
const argumentStr = s.slice(argumentStart, node.argument.end!)
79+
80+
const containsNestedAwait = /\bawait\b/.test(argumentStr)
81+
82+
s.overwrite(
83+
node.start!,
84+
argumentStart,
85+
`${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${importHelperFn(
86+
s,
87+
0,
88+
`withAsyncContext`,
89+
'vue',
90+
)}(${containsNestedAwait ? `async ` : ``}() => `,
91+
)
92+
s.appendLeft(
93+
node.end!,
94+
`)),\n ${isStatement ? `` : `__temp = `}await __temp,\n __restore()${
95+
isStatement ? `` : `,\n __temp`
96+
}\n)`,
97+
)
98+
}

0 commit comments

Comments
 (0)