Skip to content

Commit

Permalink
fix: correctly process default dynamic imports
Browse files Browse the repository at this point in the history
fix #222
  • Loading branch information
qmhc committed Jun 30, 2023
1 parent 5b7c5e5 commit 99105b0
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 33 deletions.
33 changes: 21 additions & 12 deletions src/transform.ts
Expand Up @@ -21,15 +21,26 @@ const importTypesRE = /import\s?(?:type)?\s?\{(.+)\}\s?from\s?['"].+['"]/

export function transformDynamicImport(content: string) {
const importMap = new Map<string, Set<string>>()
const defaultMap = new Map<string, string>()

let defaultCount = 1

content = content.replace(globalDynamicTypeRE, str => {
const matchResult = str.match(dynamicTypeRE)!
const libName = matchResult[1]
const importSet =
importMap.get(libName) ?? importMap.set(libName, new Set<string>()).get(libName)!
const usedType = matchResult[2]

importSet.add(usedType)
let usedType = matchResult[2]

if (usedType === 'default') {
usedType =
defaultMap.get(libName) ??
defaultMap.set(libName, `__DTS_${defaultCount++}__`).get(libName)!
importSet.add(`default as ${usedType}`)
} else {
importSet.add(usedType)
}

return usedType + matchResult[3]
})
Expand All @@ -42,13 +53,11 @@ export function transformDynamicImport(content: string) {
const matchResult = content.match(importReg)

if (matchResult?.[0]) {
const importedTypes = matchResult[0].match(importTypesRE)![1].trim().split(',')
matchResult[0].match(importTypesRE)![1].trim().split(',').forEach(importSet.add)

content = content.replace(
matchResult[0],
`import type { ${Array.from(importSet)
.concat(importedTypes)
.join(', ')} } from '${libName}'`
`import type { ${Array.from(importSet).join(', ')} } from '${libName}'`
)
} else {
content = `import type { ${Array.from(importSet).join(', ')} } from '${libName}';\n` + content
Expand All @@ -58,14 +67,14 @@ export function transformDynamicImport(content: string) {
return content
}

function isAliasMatch(alias: Alias, importee: string) {
if (isRegExp(alias.find)) return alias.find.test(importee)
if (importee.length < alias.find.length) return false
if (importee === alias.find) return true
function isAliasMatch(alias: Alias, importer: string) {
if (isRegExp(alias.find)) return alias.find.test(importer)
if (importer.length < alias.find.length) return false
if (importer === alias.find) return true

return (
importee.indexOf(alias.find) === 0 &&
(alias.find.endsWith('/') || importee.substring(alias.find.length)[0] === '/')
importer.indexOf(alias.find) === 0 &&
(alias.find.endsWith('/') || importer.substring(alias.find.length)[0] === '/')
)
}

Expand Down
50 changes: 29 additions & 21 deletions tests/transform.spec.ts
Expand Up @@ -11,39 +11,47 @@ import type { Alias } from 'vite'

describe('transform tests', () => {
it('test: normalizeGlob', () => {
expect(normalizeGlob('')).toBe('/**')
expect(normalizeGlob('/')).toBe('/**')
expect(normalizeGlob('.')).toBe('./**')
expect(normalizeGlob('..')).toBe('../**')
expect(normalizeGlob('../..')).toBe('../../**')
expect(normalizeGlob('a/b')).toBe('a/b/**')
expect(normalizeGlob('a/b/')).toBe('a/b/**')
expect(normalizeGlob('a/.b')).toBe('a/.b')
expect(normalizeGlob('a/b.c')).toBe('a/b.c')
expect(normalizeGlob('**/*')).toBe('**/*')
expect(normalizeGlob('a/b*')).toBe('a/b*/**')
expect(normalizeGlob('a/*')).toBe('a/*')
expect(normalizeGlob('a/**')).toBe('a/**')
expect(normalizeGlob('')).toEqual('/**')
expect(normalizeGlob('/')).toEqual('/**')
expect(normalizeGlob('.')).toEqual('./**')
expect(normalizeGlob('..')).toEqual('../**')
expect(normalizeGlob('../..')).toEqual('../../**')
expect(normalizeGlob('a/b')).toEqual('a/b/**')
expect(normalizeGlob('a/b/')).toEqual('a/b/**')
expect(normalizeGlob('a/.b')).toEqual('a/.b')
expect(normalizeGlob('a/b.c')).toEqual('a/b.c')
expect(normalizeGlob('**/*')).toEqual('**/*')
expect(normalizeGlob('a/b*')).toEqual('a/b*/**')
expect(normalizeGlob('a/*')).toEqual('a/*')
expect(normalizeGlob('a/**')).toEqual('a/**')
})

it('test: transformDynamicImport', () => {
expect(transformDynamicImport('data: import("vexip-ui/lib/tree").InitDataOptions[];')).toBe(
expect(transformDynamicImport('data: import("vexip-ui/lib/tree").InitDataOptions[];')).toEqual(
"import type { InitDataOptions } from 'vexip-ui/lib/tree';\ndata: InitDataOptions[];"
)

expect(
transformDynamicImport(
'declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin>;\nexport default _default;\n'
)
).toBe(
).toEqual(
"import type { DefineComponent, ComponentOptionsMixin } from 'vue';\ndeclare const _default: DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin>;\nexport default _default;\n"
)

expect(
transformDynamicImport('}> & {} & {} & import("vue").ComponentCustomProperties) | null>;')
).toBe(
).toEqual(
"import type { ComponentCustomProperties } from 'vue';\n}> & {} & {} & ComponentCustomProperties) | null>;"
)

expect(
transformDynamicImport(
'declare const _default: import("./Service").ServiceConstructor<import("./Service").default>;'
)
).toEqual(
"import type { ServiceConstructor, default as __DTS_1__ } from './Service';\ndeclare const _default: ServiceConstructor<__DTS_1__>;"
)
})

it('test: transformAliasImport', () => {
Expand All @@ -59,9 +67,9 @@ describe('transform tests', () => {
'import type { TestBase } from "@/components/test";\n',
aliases
)
).toBe("import type { TestBase } from '../components/test';\n")
).toEqual("import type { TestBase } from '../components/test';\n")

expect(transformAliasImport(filePath, 'import("@/components/test").Test;\n', aliases)).toBe(
expect(transformAliasImport(filePath, 'import("@/components/test").Test;\n', aliases)).toEqual(
"import('../components/test').Test;\n"
)

Expand All @@ -71,13 +79,13 @@ describe('transform tests', () => {
'import VContainer from "@components/layout/container/VContainer.vue";\n',
aliases
)
).toBe("import VContainer from './components/layout/container/VContainer.vue';\n")
).toEqual("import VContainer from './components/layout/container/VContainer.vue';\n")
})

it('test: removePureImport', () => {
expect(removePureImport('import "@/themes/common.scss";')).toBe('')
expect(removePureImport('import "@/themes/common.scss";')).toEqual('')
expect(
removePureImport('import "@/themes/common.scss";\nimport type { Ref } from "vue";')
).toBe('import type { Ref } from "vue";')
).toEqual('import type { Ref } from "vue";')
})
})

0 comments on commit 99105b0

Please sign in to comment.