-
Notifications
You must be signed in to change notification settings - Fork 339
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
190 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import type { CodemodPlugin } from 'vue-metamorph' | ||
import type { TransformOpts } from '.' | ||
import { ICON_LIBRARIES } from '@/src/utils/icon-libraries' | ||
|
||
// Lucide is the default icon library in the registry. | ||
const SOURCE_LIBRARY = 'lucide' | ||
|
||
export function transformIcons(opts: TransformOpts, registryIcons: Record<string, Record<string, string>>): CodemodPlugin { | ||
return { | ||
type: 'codemod', | ||
name: 'modify import of icon library on user config', | ||
|
||
transform({ scriptASTs, sfcAST, utils: { traverseScriptAST, traverseTemplateAST } }) { | ||
let transformCount = 0 | ||
const { config } = opts | ||
|
||
// No transform if we cannot read the icon library. | ||
if (!config.iconLibrary || !(config.iconLibrary in ICON_LIBRARIES)) { | ||
return transformCount | ||
} | ||
|
||
const sourceLibrary = SOURCE_LIBRARY | ||
const targetLibrary = config.iconLibrary | ||
|
||
if (sourceLibrary === targetLibrary) { | ||
return transformCount | ||
} | ||
|
||
// Map<orignalIcon, targetedIcon> | ||
const targetedIconsMap: Map<string, string> = new Map() | ||
for (const scriptAST of scriptASTs) { | ||
traverseScriptAST(scriptAST, { | ||
|
||
visitImportDeclaration(path) { | ||
if (![ICON_LIBRARIES.radix.import, ICON_LIBRARIES.lucide.import].includes(`${path.node.source.value}`)) | ||
return this.traverse(path) | ||
|
||
for (const specifier of path.node.specifiers ?? []) { | ||
if (specifier.type === 'ImportSpecifier') { | ||
const iconName = specifier.imported.name | ||
|
||
const targetedIcon = registryIcons[iconName]?.[targetLibrary] | ||
|
||
if (!targetedIcon || targetedIconsMap.has(targetedIcon)) { | ||
continue | ||
} | ||
|
||
targetedIconsMap.set(iconName, targetedIcon) | ||
specifier.imported.name = targetedIcon | ||
} | ||
} | ||
|
||
if (targetedIconsMap.size > 0) | ||
path.node.source.value = ICON_LIBRARIES[targetLibrary as keyof typeof ICON_LIBRARIES].import | ||
|
||
return this.traverse(path) | ||
}, | ||
}) | ||
|
||
if (sfcAST) { | ||
traverseTemplateAST(sfcAST, { | ||
enterNode(node) { | ||
if (node.type === 'VElement' && targetedIconsMap.has(node.rawName)) { | ||
node.rawName = targetedIconsMap.get(node.rawName) ?? '' | ||
transformCount++ | ||
} | ||
}, | ||
}) | ||
} | ||
} | ||
|
||
return transformCount | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
packages/cli/test/utils/__snapshots__/transform-icons.test.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html | ||
|
||
exports[`transformIcons > does not transform lucide icons 1`] = ` | ||
"<script setup> | ||
import { Check } from 'lucide-vue-next'; | ||
import { Primitive } from 'reka-ui'; | ||
</script> | ||
<template> | ||
<Check /> | ||
<Primitive /> | ||
</template> | ||
" | ||
`; | ||
|
||
exports[`transformIcons > transforms radix icons 1`] = ` | ||
"<script setup> | ||
import { CheckIcon } from '@radix-icons/vue'; | ||
import { Primitive } from 'reka-ui'; | ||
</script> | ||
<template> | ||
<CheckIcon /> | ||
<Primitive /> | ||
</template> | ||
" | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { describe, expect, it } from 'vitest' | ||
import { transform } from '../../src/utils/transformers' | ||
|
||
describe('transformIcons', () => { | ||
it('transforms radix icons', async () => { | ||
const result = await transform({ | ||
filename: 'app.vue', | ||
raw: `<script lang="ts" setup> | ||
import { Check } from 'lucide-vue-next' | ||
import { Primitive } from 'reka-ui' | ||
</script> | ||
<template> | ||
<Check /> | ||
<Primitive /> | ||
</template> | ||
`, | ||
config: { | ||
iconLibrary: 'radix', | ||
}, | ||
}) | ||
expect(result).toMatchSnapshot() | ||
}) | ||
|
||
it('does not transform lucide icons', async () => { | ||
const result = await transform({ | ||
filename: 'app.vue', | ||
raw: `<script lang="ts" setup> | ||
import { Check } from 'lucide-vue-next' | ||
import { Primitive } from 'reka-ui' | ||
</script> | ||
<template> | ||
<Check /> | ||
<Primitive /> | ||
</template> | ||
`, | ||
config: { | ||
iconLibrary: 'lucide', | ||
}, | ||
}) | ||
expect(result).toMatchSnapshot() | ||
}) | ||
}) |