Make tags translatable, move icons to frontend, a few other things (#5229)
* Make tags translatable, move icons to frontend, a few other things * Migrate more things * fix import * more import fixes * export tag-messages * lint
This commit is contained in:
@@ -15,7 +15,12 @@ function toPascalCase(str: string): string {
|
||||
.join('')
|
||||
}
|
||||
|
||||
function generateIconExports(): { imports: string; exports: string } {
|
||||
function generateIconExports(): {
|
||||
imports: string
|
||||
exports: string
|
||||
categoryMap: string
|
||||
loaderMap: string
|
||||
} {
|
||||
const packageRoot = path.resolve(__dirname, '..')
|
||||
const iconsDir = path.join(packageRoot, 'icons')
|
||||
|
||||
@@ -23,10 +28,17 @@ function generateIconExports(): { imports: string; exports: string } {
|
||||
throw new Error(`Icons directory not found: ${iconsDir}`)
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(iconsDir).filter((file) => file.endsWith('.svg'))
|
||||
const icons: Array<{ importPath: string; pascalName: string; privateName: string }> = []
|
||||
const categoryMapEntries: Array<{ key: string; value: string }> = []
|
||||
const loaderMapEntries: Array<{ key: string; value: string }> = []
|
||||
|
||||
// Build icon data with import paths
|
||||
const icons = files.map((file) => {
|
||||
// Process top-level icons
|
||||
const files = fs.readdirSync(iconsDir).filter((file) => {
|
||||
const filePath = path.join(iconsDir, file)
|
||||
return fs.statSync(filePath).isFile() && file.endsWith('.svg')
|
||||
})
|
||||
|
||||
files.forEach((file) => {
|
||||
const baseName = path.basename(file, '.svg')
|
||||
let pascalName = toPascalCase(baseName)
|
||||
|
||||
@@ -38,16 +50,84 @@ function generateIconExports(): { imports: string; exports: string } {
|
||||
pascalName += 'Icon'
|
||||
}
|
||||
|
||||
return {
|
||||
icons.push({
|
||||
importPath: `./icons/${file}?component`,
|
||||
pascalName,
|
||||
privateName: `_${pascalName}`,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Process tag icons from icons/tags/categories/
|
||||
const categoriesDir = path.join(iconsDir, 'tags', 'categories')
|
||||
if (fs.existsSync(categoriesDir)) {
|
||||
const categoryFiles = fs.readdirSync(categoriesDir).filter((file) => file.endsWith('.svg'))
|
||||
categoryFiles.forEach((file) => {
|
||||
const baseName = path.basename(file, '.svg')
|
||||
let pascalName = toPascalCase(baseName)
|
||||
|
||||
if (pascalName === '') {
|
||||
pascalName = 'Unknown'
|
||||
}
|
||||
|
||||
// Prefix with TagCategory
|
||||
pascalName = `TagCategory${pascalName}`
|
||||
if (!pascalName.endsWith('Icon')) {
|
||||
pascalName += 'Icon'
|
||||
}
|
||||
|
||||
icons.push({
|
||||
importPath: `./icons/tags/categories/${file}?component`,
|
||||
pascalName,
|
||||
privateName: `_${pascalName}`,
|
||||
})
|
||||
|
||||
// Add to category map (key is the original filename without extension, lowercase)
|
||||
categoryMapEntries.push({
|
||||
key: baseName.toLowerCase(),
|
||||
value: pascalName,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Process tag icons from icons/tags/loaders/
|
||||
const loadersDir = path.join(iconsDir, 'tags', 'loaders')
|
||||
if (fs.existsSync(loadersDir)) {
|
||||
const loaderFiles = fs.readdirSync(loadersDir).filter((file) => file.endsWith('.svg'))
|
||||
loaderFiles.forEach((file) => {
|
||||
const baseName = path.basename(file, '.svg')
|
||||
let pascalName = toPascalCase(baseName)
|
||||
|
||||
if (pascalName === '') {
|
||||
pascalName = 'Unknown'
|
||||
}
|
||||
|
||||
// Prefix with TagLoader
|
||||
pascalName = `TagLoader${pascalName}`
|
||||
if (!pascalName.endsWith('Icon')) {
|
||||
pascalName += 'Icon'
|
||||
}
|
||||
|
||||
icons.push({
|
||||
importPath: `./icons/tags/loaders/${file}?component`,
|
||||
pascalName,
|
||||
privateName: `_${pascalName}`,
|
||||
})
|
||||
|
||||
// Add to loader map (key is the original filename without extension, lowercase)
|
||||
loaderMapEntries.push({
|
||||
key: baseName.toLowerCase(),
|
||||
value: pascalName,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Sort by import path using simple-import-sort's algorithm
|
||||
icons.sort((a, b) => compareImportSources(a.importPath, b.importPath))
|
||||
|
||||
// Sort map entries by key for consistent output
|
||||
categoryMapEntries.sort((a, b) => a.key.localeCompare(b.key))
|
||||
loaderMapEntries.sort((a, b) => a.key.localeCompare(b.key))
|
||||
|
||||
let imports = ''
|
||||
let exports = ''
|
||||
|
||||
@@ -56,7 +136,21 @@ function generateIconExports(): { imports: string; exports: string } {
|
||||
exports += `export const ${pascalName} = ${privateName}\n`
|
||||
})
|
||||
|
||||
return { imports, exports }
|
||||
// Generate category map
|
||||
let categoryMap = 'export const categoryIconMap: Record<string, IconComponent> = {\n'
|
||||
categoryMapEntries.forEach(({ key, value }) => {
|
||||
categoryMap += `\t'${key}': ${value},\n`
|
||||
})
|
||||
categoryMap += '}\n'
|
||||
|
||||
// Generate loader map
|
||||
let loaderMap = 'export const loaderIconMap: Record<string, IconComponent> = {\n'
|
||||
loaderMapEntries.forEach(({ key, value }) => {
|
||||
loaderMap += `\t'${key}': ${value},\n`
|
||||
})
|
||||
loaderMap += '}\n'
|
||||
|
||||
return { imports, exports, categoryMap, loaderMap }
|
||||
}
|
||||
|
||||
function runTests(): void {
|
||||
@@ -106,12 +200,19 @@ function generateFiles(): void {
|
||||
try {
|
||||
console.log('🔄 Generating icon exports...')
|
||||
|
||||
const { imports, exports } = generateIconExports()
|
||||
const { imports, exports, categoryMap, loaderMap } = generateIconExports()
|
||||
const output = `// Auto-generated icon imports and exports
|
||||
// Do not edit this file manually - run 'pnpm run fix' to regenerate
|
||||
|
||||
import type { FunctionalComponent, SVGAttributes } from 'vue'
|
||||
|
||||
export type IconComponent = FunctionalComponent<SVGAttributes>
|
||||
|
||||
${imports}
|
||||
${exports}`
|
||||
${exports}
|
||||
|
||||
${categoryMap}
|
||||
${loaderMap}`
|
||||
|
||||
const packageRoot = path.resolve(__dirname, '..')
|
||||
const outputPath = path.join(packageRoot, 'generated-icons.ts')
|
||||
@@ -146,10 +247,34 @@ function getExpectedIconExports(iconsDir: string): string[] {
|
||||
return []
|
||||
}
|
||||
|
||||
return fs
|
||||
.readdirSync(iconsDir)
|
||||
.filter((file) => file.endsWith('.svg'))
|
||||
.map((file) => {
|
||||
const exports: string[] = []
|
||||
|
||||
// Process top-level icons
|
||||
const files = fs.readdirSync(iconsDir).filter((file) => {
|
||||
const filePath = path.join(iconsDir, file)
|
||||
return fs.statSync(filePath).isFile() && file.endsWith('.svg')
|
||||
})
|
||||
|
||||
files.forEach((file) => {
|
||||
const baseName = path.basename(file, '.svg')
|
||||
let pascalName = toPascalCase(baseName)
|
||||
|
||||
if (pascalName === '') {
|
||||
pascalName = 'Unknown'
|
||||
}
|
||||
|
||||
if (!pascalName.endsWith('Icon')) {
|
||||
pascalName += 'Icon'
|
||||
}
|
||||
|
||||
exports.push(pascalName)
|
||||
})
|
||||
|
||||
// Process tag icons from icons/tags/categories/
|
||||
const categoriesDir = path.join(iconsDir, 'tags', 'categories')
|
||||
if (fs.existsSync(categoriesDir)) {
|
||||
const categoryFiles = fs.readdirSync(categoriesDir).filter((file) => file.endsWith('.svg'))
|
||||
categoryFiles.forEach((file) => {
|
||||
const baseName = path.basename(file, '.svg')
|
||||
let pascalName = toPascalCase(baseName)
|
||||
|
||||
@@ -157,13 +282,37 @@ function getExpectedIconExports(iconsDir: string): string[] {
|
||||
pascalName = 'Unknown'
|
||||
}
|
||||
|
||||
pascalName = `TagCategory${pascalName}`
|
||||
if (!pascalName.endsWith('Icon')) {
|
||||
pascalName += 'Icon'
|
||||
}
|
||||
|
||||
return pascalName
|
||||
exports.push(pascalName)
|
||||
})
|
||||
.sort()
|
||||
}
|
||||
|
||||
// Process tag icons from icons/tags/loaders/
|
||||
const loadersDir = path.join(iconsDir, 'tags', 'loaders')
|
||||
if (fs.existsSync(loadersDir)) {
|
||||
const loaderFiles = fs.readdirSync(loadersDir).filter((file) => file.endsWith('.svg'))
|
||||
loaderFiles.forEach((file) => {
|
||||
const baseName = path.basename(file, '.svg')
|
||||
let pascalName = toPascalCase(baseName)
|
||||
|
||||
if (pascalName === '') {
|
||||
pascalName = 'Unknown'
|
||||
}
|
||||
|
||||
pascalName = `TagLoader${pascalName}`
|
||||
if (!pascalName.endsWith('Icon')) {
|
||||
pascalName += 'Icon'
|
||||
}
|
||||
|
||||
exports.push(pascalName)
|
||||
})
|
||||
}
|
||||
|
||||
return exports.sort()
|
||||
}
|
||||
|
||||
function getActualIconExports(indexFile: string): string[] {
|
||||
|
||||
Reference in New Issue
Block a user