Skip to content

Commit eed6976

Browse files
committed
feat(declaration): preserve previous declartions and sort the result
1 parent 1c6db6c commit eed6976

File tree

2 files changed

+50
-32
lines changed

2 files changed

+50
-32
lines changed

examples/vue3/components.d.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@
33

44
declare module 'vue' {
55
export interface GlobalComponents {
6+
Avatar: typeof import('./src/components/global/avatar.vue')['default']
7+
Book: typeof import('./src/components/book/index.vue')['default']
68
CarbonSvg: typeof import('./src/components/CarbonSvg.svg')['default']
79
ComponentA: typeof import('./src/components/ComponentA.vue')['default']
810
ComponentB: typeof import('./src/components/ComponentB.vue')['default']
11+
ComponentC: typeof import('./src/components/component-c.vue')['default']
912
ComponentD: typeof import('./src/components/ComponentD.vue')['default']
13+
IFaSolidDiceFive: typeof import('virtual:vite-icons/fa-solid/dice-five')['default']
14+
IHeroiconsOutlineMenuAlt2: typeof import('virtual:vite-icons/heroicons-outline/menu-alt2')['default']
15+
'IMdi:diceD12': typeof import('virtual:vite-icons/mdi/dice-d12')['default']
16+
IMdiLightAlarm: typeof import('virtual:vite-icons/mdi-light/alarm')['default']
17+
IRiApps2Line: typeof import('virtual:vite-icons/ri/apps2-line')['default']
1018
MarkdownA: typeof import('./src/components/MarkdownA.md')['default']
1119
MarkdownB: typeof import('./src/components/MarkdownB.md')['default']
20+
MyCustom: typeof import('./src/CustomResolved.vue')['default']
1221
Recursive: typeof import('./src/components/Recursive.vue')['default']
13-
ComponentC: typeof import('./src/components/component-c.vue')['default']
14-
Book: typeof import('./src/components/book/index.vue')['default']
15-
Avatar: typeof import('./src/components/global/avatar.vue')['default']
1622
UiButton: typeof import('./src/components/ui/button.vue')['default']
1723
UiNestedCheckbox: typeof import('./src/components/ui/nested/checkbox.vue')['default']
18-
MyCustom: typeof import('./src/CustomResolved.vue')['default']
19-
VanRate: typeof import('vant/es')['Rate']
2024
VanRadio: typeof import('vant/es')['Radio']
2125
VanRadioGroup: typeof import('vant/es')['RadioGroup']
22-
IFaSolidDiceFive: typeof import('virtual:vite-icons/fa-solid/dice-five')['default']
23-
IHeroiconsOutlineMenuAlt2: typeof import('virtual:vite-icons/heroicons-outline/menu-alt2')['default']
24-
IRiApps2Line: typeof import('virtual:vite-icons/ri/apps2-line')['default']
25-
'IMdi:diceD12': typeof import('virtual:vite-icons/mdi/dice-d12')['default']
26-
IMdiLightAlarm: typeof import('virtual:vite-icons/mdi-light/alarm')['default']
26+
VanRate: typeof import('vant/es')['Rate']
2727
}
2828
}
2929

src/declaration.ts

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,54 @@
11
import { resolve, dirname, relative } from 'path'
2-
import { promises as fs } from 'fs'
2+
import { promises as fs, existsSync } from 'fs'
33
import { notNullish } from '@antfu/utils'
44
import { Context } from './context'
55
import { slash } from './utils'
66

7+
export function parseDeclaration(code: string): Record<string, string> {
8+
return Object.fromEntries(Array.from(code.matchAll(/\s+['"]?(.+?)['"]?:\s(.+?)\n/g)).map(i => [i[1], i[2]]))
9+
}
10+
711
export async function generateDeclaration(ctx: Context, root: string, filepath: string) {
8-
const lines = Object.values({
9-
...ctx.componentNameMap,
10-
...ctx.componentCustomMap,
11-
})
12-
.map(({ path, name, importName }) => {
13-
if (!name)
14-
return undefined
12+
const imports: Record<string, string> = Object.fromEntries(
13+
Object.values({
14+
...ctx.componentNameMap,
15+
...ctx.componentCustomMap,
16+
})
17+
.map(({ path, name, importName }) => {
18+
if (!name)
19+
return undefined
20+
21+
const related = slash(path).startsWith('/')
22+
? `./${relative(dirname(filepath), resolve(root, path.slice(1)))}`
23+
: path
24+
25+
let entry = `typeof import('${slash(related)}')`
26+
if (importName)
27+
entry += `['${importName}']`
28+
else
29+
entry += '[\'default\']'
30+
return [name, entry]
31+
})
32+
.filter(notNullish),
33+
)
1534

16-
const related = slash(path).startsWith('/')
17-
? `./${relative(dirname(filepath), resolve(root, path.slice(1)))}`
18-
: path
35+
if (!Object.keys(imports).length)
36+
return
37+
38+
const originalImports = existsSync(filepath)
39+
? parseDeclaration(await fs.readFile(filepath, 'utf-8'))
40+
: {}
1941

42+
const lines = Object.entries({
43+
...originalImports,
44+
...imports,
45+
})
46+
.sort((a, b) => a[0].localeCompare(b[0]))
47+
.map(([name, v]) => {
2048
if (!/^\w+$/.test(name))
2149
name = `'${name}'`
22-
23-
let entry = `${name}: typeof import('${slash(related)}')`
24-
if (importName)
25-
entry += `['${importName}']`
26-
else
27-
entry += '[\'default\']'
28-
return entry
50+
return `${name}: ${v}`
2951
})
30-
.filter(notNullish)
31-
32-
if (!lines.length)
33-
return
3452

3553
const code = `// generated by vite-plugin-components
3654
// read more https://github.com/vuejs/vue-next/pull/3399

0 commit comments

Comments
 (0)