|
1 | 1 | import { resolve, dirname, relative } from 'path'
|
2 |
| -import { promises as fs } from 'fs' |
| 2 | +import { promises as fs, existsSync } from 'fs' |
3 | 3 | import { notNullish } from '@antfu/utils'
|
4 | 4 | import { Context } from './context'
|
5 | 5 | import { slash } from './utils'
|
6 | 6 |
|
| 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 | + |
7 | 11 | 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 | + ) |
15 | 34 |
|
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 | + : {} |
19 | 41 |
|
| 42 | + const lines = Object.entries({ |
| 43 | + ...originalImports, |
| 44 | + ...imports, |
| 45 | + }) |
| 46 | + .sort((a, b) => a[0].localeCompare(b[0])) |
| 47 | + .map(([name, v]) => { |
20 | 48 | if (!/^\w+$/.test(name))
|
21 | 49 | 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}` |
29 | 51 | })
|
30 |
| - .filter(notNullish) |
31 |
| - |
32 |
| - if (!lines.length) |
33 |
| - return |
34 | 52 |
|
35 | 53 | const code = `// generated by vite-plugin-components
|
36 | 54 | // read more https://github.com/vuejs/vue-next/pull/3399
|
|
0 commit comments