| #!/usr/bin/env node |
|
|
| import fs from 'fs/promises'; |
| import path from 'path'; |
| import { fileURLToPath } from 'url'; |
|
|
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); |
|
|
| |
| const TYPOGRAPHY_BASE = __dirname; |
| const GENERATED_DIR = path.join(TYPOGRAPHY_BASE, 'generated'); |
| const SVGS_DIR = path.join(GENERATED_DIR, 'svgs'); |
| const DATA_DIR = path.join(GENERATED_DIR, 'data'); |
| const SPRITES_DIR = path.join(GENERATED_DIR, 'sprites'); |
| const OUTPUT_SPRITE = path.join(SPRITES_DIR, 'font-sprite.svg'); |
|
|
| async function generateSvgSprite() { |
| console.log('π¨ Generating SVG sprite...'); |
|
|
| try { |
| |
| const files = await fs.readdir(SVGS_DIR); |
| const svgFiles = files.filter(file => file.endsWith('.svg')); |
|
|
| console.log(`π Found ${svgFiles.length} SVG files`); |
|
|
| let sprites = []; |
| let processedCount = 0; |
|
|
| |
| for (const file of svgFiles) { |
| try { |
| const filePath = path.join(SVGS_DIR, file); |
| const content = await fs.readFile(filePath, 'utf-8'); |
|
|
| |
| const match = content.match(/<svg[^>]*>(.*?)<\/svg>/s); |
| if (!match) continue; |
|
|
| const innerContent = match[1].trim(); |
| if (!innerContent) continue; |
|
|
| |
| const symbolId = file.replace('.svg', ''); |
|
|
| |
| const viewBoxMatch = content.match(/viewBox=["']([^"']+)["']/); |
| const viewBox = viewBoxMatch ? viewBoxMatch[1] : '0 0 80 80'; |
|
|
| |
| sprites.push(` <symbol id="${symbolId}" viewBox="${viewBox}"> |
| ${innerContent} |
| </symbol>`); |
|
|
| processedCount++; |
|
|
| if (processedCount % 100 === 0) { |
| console.log(`β‘ Processed ${processedCount}/${svgFiles.length} SVGs...`); |
| } |
|
|
| } catch (error) { |
| console.warn(`β οΈ Error with ${file}:`, error.message); |
| } |
| } |
|
|
| |
| const spriteContent = `<?xml version="1.0" encoding="UTF-8"?> |
| <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;"> |
| <defs> |
| ${sprites.join('\n')} |
| </defs> |
| </svg>`; |
|
|
| |
| await fs.mkdir(path.dirname(OUTPUT_SPRITE), { recursive: true }); |
|
|
| |
| await fs.writeFile(OUTPUT_SPRITE, spriteContent, 'utf-8'); |
|
|
| console.log(`β
SVG sprite generated with ${sprites.length} symbols`); |
| console.log(`π File: ${OUTPUT_SPRITE}`); |
| console.log(`π Size: ${(spriteContent.length / 1024).toFixed(1)} KB`); |
|
|
| |
| const mapping = {}; |
| svgFiles.forEach(file => { |
| const fontName = file.replace('_a.svg', '').replace(/_/g, ' '); |
| const symbolId = file.replace('.svg', ''); |
| mapping[fontName] = symbolId; |
| }); |
|
|
| const mappingFile = path.join(DATA_DIR, 'font-sprite-mapping.json'); |
| await fs.writeFile(mappingFile, JSON.stringify(mapping, null, 2)); |
|
|
| console.log(`πΊοΈ Mapping generated: ${mappingFile}`); |
|
|
| } catch (error) { |
| console.error('β Error during generation:', error); |
| process.exit(1); |
| } |
| } |
|
|
| |
| if (import.meta.url === `file://${process.argv[1]}`) { |
| generateSvgSprite(); |
| } |
|
|
| export { generateSvgSprite }; |
|
|