-
-
Notifications
You must be signed in to change notification settings - Fork 367
/
Copy pathdeclaration.ts
76 lines (65 loc) · 2.23 KB
/
declaration.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { dirname, isAbsolute, relative } from 'path'
import { existsSync, promises as fs } from 'fs'
import { notNullish, slash } from '@antfu/utils'
import type { Context } from './context'
import { getTransformedPath } from './utils'
import { resolveTypeImports } from './type-imports/detect'
export function parseDeclaration(code: string): Record<string, string> {
if (!code)
return {}
return Object.fromEntries(Array.from(code.matchAll(/(?<!\/\/)\s+\s+['"]?(.+?)['"]?:\s(.+?)\n/g)).map(i => [i[1], i[2]]))
}
export async function generateDeclaration(ctx: Context, root: string, filepath: string, removeUnused = false): Promise<void> {
const items = [
...Object.values({
...ctx.componentNameMap,
...ctx.componentCustomMap,
}),
...resolveTypeImports(ctx.options.types),
]
const imports: Record<string, string> = Object.fromEntries(
items.map(({ from: path, as: name, name: importName }) => {
if (!name)
return undefined
path = getTransformedPath(path, ctx)
const related = isAbsolute(path)
? `./${relative(dirname(filepath), path)}`
: path
let entry = `typeof import('${slash(related)}')`
if (importName)
entry += `['${importName}']`
else
entry += '[\'default\']'
return [name, entry]
})
.filter(notNullish),
)
if (!Object.keys(imports).length)
return
const originalContent = existsSync(filepath) ? await fs.readFile(filepath, 'utf-8') : ''
const originalImports = parseDeclaration(originalContent)
const lines = Object.entries({
...originalImports,
...imports,
})
.sort((a, b) => a[0].localeCompare(b[0]))
.filter(([name]) => removeUnused ? items.find(i => i.as === name) : true)
.map(([name, v]) => {
if (!/^\w+$/.test(name))
name = `'${name}'`
return `${name}: ${v}`
})
const code = `// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399
import '@vue/runtime-core'
declare module '@vue/runtime-core' {
export interface GlobalComponents {
${lines.join('\n ')}
}
}
export {}
`
if (code !== originalContent)
await fs.writeFile(filepath, code, 'utf-8')
}