Skip to content

Commit 12eb4cd

Browse files
authored
fix(vue): add HTML attributes to generated TypeScript types (#15016)
* fix(vue): add HTML attributes to generated TypeScript types Fixes #14686 * fix: add package exports and update tests for HTML attributes support * test(vue): add astro check test for HTML attributes Add test fixture and test case to verify that Vue components correctly accept HTML attributes (class, style, id, data-*) and client directives via astro check. Follows the same pattern as the Svelte integration tests. * chore: update lockfile for vue prop-types fixture
1 parent b1e8e32 commit 12eb4cd

File tree

14 files changed

+110
-6
lines changed

14 files changed

+110
-6
lines changed

.changeset/kind-emus-relate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/vue': patch
3+
---
4+
5+
Adds support for arbitrary HTML attributes on Vue components

packages/integrations/vue/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
"./editor": "./dist/editor.cjs",
2525
"./client.js": "./dist/client.js",
2626
"./server.js": "./dist/server.js",
27+
"./vue-shims.d.ts": "./vue-shims.d.ts",
2728
"./package.json": "./package.json"
2829
},
2930
"files": [
30-
"dist"
31+
"dist",
32+
"vue-shims.d.ts"
3133
],
3234
"scripts": {
3335
"build": "astro-scripts build \"src/**/*.ts\" && astro-scripts build \"src/editor.cts\" --force-cjs --no-clean-dist && tsc",

packages/integrations/vue/src/editor.cts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { parse } from '@vue/compiler-sfc';
22

33
export function toTSX(code: string, className: string): string {
4-
let result = `export default function ${className}__AstroComponent_(_props: Record<string, any>): any {}`;
4+
let result = `export default function ${className}__AstroComponent_(_props: import('@astrojs/vue/vue-shims.d.ts').PropsWithHTMLAttributes<Record<string, any>>): any {}`;
55

66
// NOTE: As you can expect, using regexes for this is not exactly the most reliable way of doing things
77
// However, I couldn't figure out a way to do it using Vue's compiler, I tried looking at how Volar does it, but I
@@ -33,7 +33,7 @@ export function toTSX(code: string, className: string): string {
3333
${regularScriptBlockContent}
3434
${scriptSetup.content}
3535
36-
export default function ${className}__AstroComponent_${propsGenericType}(_props: ${definePropsType[1]}): any {
36+
export default function ${className}__AstroComponent_${propsGenericType}(_props: import('@astrojs/vue/vue-shims.d.ts').PropsWithHTMLAttributes<${definePropsType[1]}>): any {
3737
<div></div>
3838
}
3939
`;
@@ -50,7 +50,7 @@ export function toTSX(code: string, className: string): string {
5050
5151
const Props = ${defineProps[0]}
5252
53-
export default function ${className}__AstroComponent_${propsGenericType}(_props: typeof Props): any {
53+
export default function ${className}__AstroComponent_${propsGenericType}(_props: import('@astrojs/vue/vue-shims.d.ts').PropsWithHTMLAttributes<typeof Props>): any {
5454
<div></div>
5555
}
5656
`;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import assert from 'node:assert/strict';
2+
import { describe, it } from 'node:test';
3+
import { fileURLToPath } from 'node:url';
4+
import { cli } from '../../../astro/test/test-utils.js';
5+
6+
describe('Vue Check', () => {
7+
it('should pass check for client directives and HTML attributes on Vue components', async () => {
8+
const root = fileURLToPath(new URL('./fixtures/prop-types/types/directive', import.meta.url));
9+
const tsConfigPath = fileURLToPath(
10+
new URL('./fixtures/prop-types/tsconfig.directive.json', import.meta.url),
11+
);
12+
const { getResult } = cli('check', '--tsconfig', tsConfigPath, '--root', root);
13+
const { exitCode, stdout, stderr } = await getResult();
14+
15+
if (exitCode !== 0) {
16+
console.error(stdout);
17+
console.error(stderr);
18+
}
19+
assert.equal(exitCode, 0, 'Expected check to pass (exit code 0)');
20+
});
21+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'astro/config';
2+
import vue from '@astrojs/vue';
3+
4+
export default defineConfig({
5+
srcDir: './types',
6+
integrations: [vue()]
7+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "vue-prop-types",
3+
"type": "module",
4+
"version": "0.0.1",
5+
"scripts": {
6+
"dev": "astro dev",
7+
"build": "astro build",
8+
"preview": "astro preview",
9+
"astro": "astro"
10+
},
11+
"dependencies": {
12+
"@astrojs/vue": "workspace:*",
13+
"astro": "workspace:*",
14+
"vue": "^3.5.13"
15+
}
16+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"include": ["types/directive"]
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"extends": "astro/tsconfigs/strict",
3+
"include": [".astro/types.d.ts", "**/*"],
4+
"exclude": ["dist"]
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script setup lang="ts">
2+
// A component that accepts arbitrary HTML attributes via Vue's $attrs fallthrough
3+
</script>
4+
5+
<template>
6+
<div v-bind="$attrs">Arbitrary</div>
7+
</template>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script setup lang="ts">
2+
// A component with strictly typed props
3+
defineProps<{
4+
message: string;
5+
}>();
6+
</script>
7+
8+
<template>
9+
<div>{{ message }}</div>
10+
</template>

0 commit comments

Comments
 (0)