import { readFileSync, writeFileSync, readdirSync } from 'node:fs'
import { join } from 'node:path'
const SRC_DIR = 'D:\\Code\\verify\\frontend\\src'
function getAllFiles(dir, exts) {
const results = []
const entries = readdirSync(dir, { withFileTypes: true })
for (const entry of entries) {
const fullPath = join(dir, entry.name)
if (entry.isDirectory()) {
results.push(...getAllFiles(fullPath, exts))
} else if (exts.some(ext => entry.name.endsWith(ext))) {
results.push(fullPath)
}
}
return results
}
function lucideToPascal(kebab) {
return kebab
.split('-')
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join('')
}
function processFile(filePath) {
let content = readFileSync(filePath, 'utf-8')
const originalContent = content
if (!content.includes('@iconify/vue') && !content.includes('icon="lucide:') && !content.includes("icon='lucide:") && !content.includes('h(Icon')) {
return null
}
const usedIcons = new Set()
// Step 1: Replace (single line)
content = content.replace(/]*)\/>/g, (match, iconName, restAttrs) => {
const pascalName = lucideToPascal(iconName)
usedIcons.add(pascalName)
const trimmedAttrs = restAttrs.trim()
if (trimmedAttrs) {
return `<${pascalName} ${trimmedAttrs} />`
}
return `<${pascalName} />`
})
// Step 2: Replace multiline
content = content.replace(/]*?)icon="lucide:([a-z0-9-]+)"([^>]*?)\/>/gs, (match, before, iconName, after) => {
const pascalName = lucideToPascal(iconName)
usedIcons.add(pascalName)
const newAttrs = (before + after).replace(/\s+/g, ' ').trim()
if (newAttrs) {
return `<${pascalName} ${newAttrs} />`
}
return `<${pascalName} />`
})
// Step 3: Replace h(Icon, { icon: 'lucide:xxx', ... }) in columns.ts files
content = content.replace(/h\(\s*Icon\s*,\s*\{\s*icon:\s*['"]lucide:([a-z0-9-]+)['"]\s*,?\s*([^}]*)\}\s*\)/g, (match, iconName, restProps) => {
const pascalName = lucideToPascal(iconName)
usedIcons.add(pascalName)
const trimmedProps = restProps.trim().replace(/,\s*$/, '')
if (trimmedProps) {
return `h(${pascalName}, { ${trimmedProps} })`
}
return `h(${pascalName})`
})
// Step 4: Replace import { Icon } from '@iconify/vue'
content = content.replace(/import\s*\{\s*Icon\s*\}\s*from\s*['"]@iconify\/vue['"]\s*\n?/g, '')
// Step 5: Add lucide-vue-next import if we used any icons
if (usedIcons.size > 0 && !content.includes("from 'lucide-vue-next'") && !content.includes('from "lucide-vue-next"')) {
const sortedIcons = [...usedIcons].sort()
const importLine = `import { ${sortedIcons.join(', ')} } from 'lucide-vue-next'\n`
const firstImportMatch = content.match(/^import\s/m)
if (firstImportMatch) {
const insertPos = content.indexOf(firstImportMatch[0])
content = content.slice(0, insertPos) + importLine + content.slice(insertPos)
} else {
content = content.replace(/(