Skip to content

Commit

Permalink
feat(declaration): preserve previous declartions and sort the result
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Jul 2, 2021
1 parent 1c6db6c commit eed6976
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 32 deletions.
20 changes: 10 additions & 10 deletions examples/vue3/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@

declare module 'vue' {
export interface GlobalComponents {
Avatar: typeof import('./src/components/global/avatar.vue')['default']
Book: typeof import('./src/components/book/index.vue')['default']
CarbonSvg: typeof import('./src/components/CarbonSvg.svg')['default']
ComponentA: typeof import('./src/components/ComponentA.vue')['default']
ComponentB: typeof import('./src/components/ComponentB.vue')['default']
ComponentC: typeof import('./src/components/component-c.vue')['default']
ComponentD: typeof import('./src/components/ComponentD.vue')['default']
IFaSolidDiceFive: typeof import('virtual:vite-icons/fa-solid/dice-five')['default']
IHeroiconsOutlineMenuAlt2: typeof import('virtual:vite-icons/heroicons-outline/menu-alt2')['default']
'IMdi:diceD12': typeof import('virtual:vite-icons/mdi/dice-d12')['default']
IMdiLightAlarm: typeof import('virtual:vite-icons/mdi-light/alarm')['default']
IRiApps2Line: typeof import('virtual:vite-icons/ri/apps2-line')['default']
MarkdownA: typeof import('./src/components/MarkdownA.md')['default']
MarkdownB: typeof import('./src/components/MarkdownB.md')['default']
MyCustom: typeof import('./src/CustomResolved.vue')['default']
Recursive: typeof import('./src/components/Recursive.vue')['default']
ComponentC: typeof import('./src/components/component-c.vue')['default']
Book: typeof import('./src/components/book/index.vue')['default']
Avatar: typeof import('./src/components/global/avatar.vue')['default']
UiButton: typeof import('./src/components/ui/button.vue')['default']
UiNestedCheckbox: typeof import('./src/components/ui/nested/checkbox.vue')['default']
MyCustom: typeof import('./src/CustomResolved.vue')['default']
VanRate: typeof import('vant/es')['Rate']
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
IFaSolidDiceFive: typeof import('virtual:vite-icons/fa-solid/dice-five')['default']
IHeroiconsOutlineMenuAlt2: typeof import('virtual:vite-icons/heroicons-outline/menu-alt2')['default']
IRiApps2Line: typeof import('virtual:vite-icons/ri/apps2-line')['default']
'IMdi:diceD12': typeof import('virtual:vite-icons/mdi/dice-d12')['default']
IMdiLightAlarm: typeof import('virtual:vite-icons/mdi-light/alarm')['default']
VanRate: typeof import('vant/es')['Rate']
}
}

Expand Down
62 changes: 40 additions & 22 deletions src/declaration.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,54 @@
import { resolve, dirname, relative } from 'path'
import { promises as fs } from 'fs'
import { promises as fs, existsSync } from 'fs'
import { notNullish } from '@antfu/utils'
import { Context } from './context'
import { slash } from './utils'

export function parseDeclaration(code: string): Record<string, string> {
return Object.fromEntries(Array.from(code.matchAll(/\s+['"]?(.+?)['"]?:\s(.+?)\n/g)).map(i => [i[1], i[2]]))
}

export async function generateDeclaration(ctx: Context, root: string, filepath: string) {
const lines = Object.values({
...ctx.componentNameMap,
...ctx.componentCustomMap,
})
.map(({ path, name, importName }) => {
if (!name)
return undefined
const imports: Record<string, string> = Object.fromEntries(
Object.values({
...ctx.componentNameMap,
...ctx.componentCustomMap,
})
.map(({ path, name, importName }) => {
if (!name)
return undefined

const related = slash(path).startsWith('/')
? `./${relative(dirname(filepath), resolve(root, path.slice(1)))}`
: path

let entry = `typeof import('${slash(related)}')`
if (importName)
entry += `['${importName}']`
else
entry += '[\'default\']'
return [name, entry]
})
.filter(notNullish),
)

const related = slash(path).startsWith('/')
? `./${relative(dirname(filepath), resolve(root, path.slice(1)))}`
: path
if (!Object.keys(imports).length)
return

const originalImports = existsSync(filepath)
? parseDeclaration(await fs.readFile(filepath, 'utf-8'))
: {}

const lines = Object.entries({
...originalImports,
...imports,
})
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([name, v]) => {
if (!/^\w+$/.test(name))
name = `'${name}'`

let entry = `${name}: typeof import('${slash(related)}')`
if (importName)
entry += `['${importName}']`
else
entry += '[\'default\']'
return entry
return `${name}: ${v}`
})
.filter(notNullish)

if (!lines.length)
return

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

0 comments on commit eed6976

Please sign in to comment.