UNPKG

image-asset-manager

Version:

A comprehensive image asset management tool for frontend projects

418 lines (409 loc) 17 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeDefinitionGenerator = void 0; const path_1 = __importDefault(require("path")); class TypeDefinitionGenerator { /** * Generate TypeScript type definitions for all image files */ async generateTypeDefinitions(files) { const typeDefinitions = []; // Add header comment typeDefinitions.push("// Auto-generated image asset type definitions"); typeDefinitions.push("// Do not edit this file manually"); typeDefinitions.push(""); // Handle empty files array if (files.length === 0) { typeDefinitions.push("// Image path types"); typeDefinitions.push(""); typeDefinitions.push("// Image path constants"); typeDefinitions.push(""); typeDefinitions.push("// Union type for all image paths"); typeDefinitions.push("export type ImageAssetPath = never;"); typeDefinitions.push(""); typeDefinitions.push("// Image metadata interface"); typeDefinitions.push("export interface ImageAssetInfo {"); typeDefinitions.push(" path: string;"); typeDefinitions.push(" name: string;"); typeDefinitions.push(" extension: string;"); typeDefinitions.push(" size: number;"); typeDefinitions.push(" dimensions: { width: number; height: number };"); typeDefinitions.push(" category: string;"); typeDefinitions.push("}"); typeDefinitions.push(""); typeDefinitions.push("// Image registry with metadata"); typeDefinitions.push("export const IMAGE_REGISTRY: Record<ImageAssetPath, ImageAssetInfo> = {"); typeDefinitions.push("};"); typeDefinitions.push(""); typeDefinitions.push("// Helper functions"); typeDefinitions.push("export function getImageInfo(path: ImageAssetPath): ImageAssetInfo {"); typeDefinitions.push(" return IMAGE_REGISTRY[path];"); typeDefinitions.push("}"); typeDefinitions.push(""); typeDefinitions.push("export function getAllImages(): ImageAssetPath[] {"); typeDefinitions.push(" return Object.keys(IMAGE_REGISTRY) as ImageAssetPath[];"); typeDefinitions.push("}"); typeDefinitions.push(""); typeDefinitions.push("export function getImagesByCategory(category: string): ImageAssetPath[] {"); typeDefinitions.push(" return Object.entries(IMAGE_REGISTRY)"); typeDefinitions.push(" .filter(([, info]) => info.category === category)"); typeDefinitions.push(" .map(([path]) => path as ImageAssetPath);"); typeDefinitions.push("}"); return typeDefinitions.join("\n"); } // Generate individual image types const imageTypes = []; const imageConstants = []; files.forEach((file) => { const typeName = this.generateTypeName(file); const constantName = this.generateConstantName(file); const relativePath = file.relativePath; // Create type definition imageTypes.push(`export type ${typeName} = "${relativePath}";`); // Create constant imageConstants.push(`export const ${constantName}: ${typeName} = "${relativePath}";`); }); // Add image types section typeDefinitions.push("// Image path types"); typeDefinitions.push(...imageTypes); typeDefinitions.push(""); // Add image constants section typeDefinitions.push("// Image path constants"); typeDefinitions.push(...imageConstants); typeDefinitions.push(""); // Generate union type for all images const allImageTypes = files .map((file) => this.generateTypeName(file)) .join(" | "); typeDefinitions.push("// Union type for all image paths"); typeDefinitions.push(`export type ImageAssetPath = ${allImageTypes};`); typeDefinitions.push(""); // Generate image metadata interface typeDefinitions.push("// Image metadata interface"); typeDefinitions.push("export interface ImageAssetInfo {"); typeDefinitions.push(" path: string;"); typeDefinitions.push(" name: string;"); typeDefinitions.push(" extension: string;"); typeDefinitions.push(" size: number;"); typeDefinitions.push(" dimensions: { width: number; height: number };"); typeDefinitions.push(" category: string;"); typeDefinitions.push("}"); typeDefinitions.push(""); // Generate image registry const imageRegistry = this.generateImageRegistry(files); typeDefinitions.push("// Image registry with metadata"); typeDefinitions.push("export const IMAGE_REGISTRY: Record<ImageAssetPath, ImageAssetInfo> = {"); typeDefinitions.push(imageRegistry); typeDefinitions.push("};"); typeDefinitions.push(""); // Generate helper functions typeDefinitions.push("// Helper functions"); typeDefinitions.push("export function getImageInfo(path: ImageAssetPath): ImageAssetInfo {"); typeDefinitions.push(" return IMAGE_REGISTRY[path];"); typeDefinitions.push("}"); typeDefinitions.push(""); typeDefinitions.push("export function getAllImages(): ImageAssetPath[] {"); typeDefinitions.push(" return Object.keys(IMAGE_REGISTRY) as ImageAssetPath[];"); typeDefinitions.push("}"); typeDefinitions.push(""); typeDefinitions.push("export function getImagesByCategory(category: string): ImageAssetPath[] {"); typeDefinitions.push(" return Object.entries(IMAGE_REGISTRY)"); typeDefinitions.push(" .filter(([, info]) => info.category === category)"); typeDefinitions.push(" .map(([path]) => path as ImageAssetPath);"); typeDefinitions.push("}"); return typeDefinitions.join("\n"); } /** * Generate import file for easy access to all image assets */ async generateImportFile(files) { const imports = []; // Add header comment imports.push("// Auto-generated image asset imports"); imports.push("// Do not edit this file manually"); imports.push(""); // Import type definitions imports.push("export * from './image-assets.types';"); imports.push(""); // Generate default exports for each image imports.push("// Default image exports"); files.forEach((file) => { const constantName = this.generateConstantName(file); imports.push(`export { default as ${constantName}Default } from '${file.relativePath}';`); }); imports.push(""); // Generate image map for dynamic access imports.push("// Dynamic image map"); imports.push("const imageMap = {"); files.forEach((file) => { imports.push(` '${file.relativePath}': () => import('${file.relativePath}'),`); }); imports.push("};"); imports.push(""); imports.push("export async function loadImage(path: string): Promise<any> {"); imports.push(" const loader = imageMap[path as keyof typeof imageMap];"); imports.push(" if (!loader) {"); imports.push(" throw new Error(`Image not found: ${path}`);"); imports.push(" }"); imports.push(" return await loader();"); imports.push("}"); return imports.join("\n"); } /** * Generate usage code for a specific framework */ generateUsageCode(file, framework) { const template = this.getCodeTemplate(framework); const constantName = this.generateConstantName(file); return template.usageTemplate .replace(/\{constantName\}/g, constantName) .replace(/\{fileName\}/g, file.name) .replace(/\{filePath\}/g, file.relativePath) .replace(/\{extension\}/g, file.extension); } /** * Generate icon component for SVG files */ generateIconComponent(file, framework) { if (file.extension.toLowerCase() !== ".svg") { throw new Error("Icon components can only be generated for SVG files"); } const template = this.getCodeTemplate(framework); if (!template.componentTemplate) { throw new Error(`Component template not available for framework: ${framework}`); } const componentName = this.generateComponentName(file); const constantName = this.generateConstantName(file); return template.componentTemplate .replace(/\{componentName\}/g, componentName) .replace(/\{constantName\}/g, constantName) .replace(/\{fileName\}/g, file.name) .replace(/\{filePath\}/g, file.relativePath); } /** * Generate inline SVG code */ generateInlineCode(file, framework) { if (file.extension.toLowerCase() !== ".svg") { throw new Error("Inline code can only be generated for SVG files"); } const template = this.getCodeTemplate(framework); if (!template.inlineTemplate) { throw new Error(`Inline template not available for framework: ${framework}`); } return template.inlineTemplate .replace(/\{fileName\}/g, file.name) .replace(/\{filePath\}/g, file.relativePath); } /** * Get all generated code for a file and framework */ generateAllCode(file, framework) { const result = { import: this.generateImportCode(file, framework), usage: this.generateUsageCode(file, framework), }; if (file.extension.toLowerCase() === ".svg") { // Try to generate component (may not be available for all frameworks) try { result.component = this.generateIconComponent(file, framework); } catch (error) { // Component generation failed, continue without component } // Try to generate inline code (should be available for all frameworks) try { result.inline = this.generateInlineCode(file, framework); } catch (error) { // Inline generation failed, continue without inline } } return result; } generateImportCode(file, framework) { const template = this.getCodeTemplate(framework); const constantName = this.generateConstantName(file); return template.importTemplate .replace(/\{constantName\}/g, constantName) .replace(/\{filePath\}/g, file.relativePath); } generateTypeName(file) { const baseName = this.sanitizeName(path_1.default.parse(file.name).name); return `${baseName}ImagePath`; } generateConstantName(file) { const fileName = path_1.default.parse(file.name).name; // For constants, we want to keep underscores between words let sanitized = fileName .replace(/[^a-zA-Z0-9]/g, "_") .replace(/_+/g, "_") .replace(/^_|_$/g, "") .toUpperCase(); // Prefix with underscore if starts with number if (/^[0-9]/.test(sanitized)) { sanitized = "_" + sanitized; } return `${sanitized}_IMAGE`; } generateComponentName(file) { const baseName = this.sanitizeName(path_1.default.parse(file.name).name); return `${baseName.charAt(0).toUpperCase() + baseName.slice(1)}Icon`; } sanitizeName(name) { // Convert to camelCase and remove invalid characters let sanitized = name .replace(/[^a-zA-Z0-9]/g, "_") .replace(/_+/g, "_") .replace(/^_|_$/g, ""); // Convert to camelCase - handle both lowercase and uppercase letters sanitized = sanitized.replace(/_([a-zA-Z])/g, (_, letter) => letter.toUpperCase()); // Prefix with underscore if starts with number if (/^[0-9]/.test(sanitized)) { sanitized = "_" + sanitized; } return sanitized; } generateImageRegistry(files) { const entries = files.map((file) => { const typeName = this.generateTypeName(file); return ` "${file.relativePath}" as ${typeName}: { path: "${file.relativePath}", name: "${file.name}", extension: "${file.extension}", size: ${file.size}, dimensions: { width: ${file.dimensions.width}, height: ${file.dimensions.height} }, category: "${file.category}" }`; }); return entries.join(",\n"); } getCodeTemplate(framework) { const templates = { react: { framework: "react", importTemplate: "import {constantName} from '../assets/images';", usageTemplate: `<img src={${"{constantName}"}} alt="{fileName}" />`, componentTemplate: `import React from 'react'; import {constantName} from '../assets/images'; interface {componentName}Props { className?: string; size?: number; color?: string; } export const {componentName}: React.FC<{componentName}Props> = ({ className, size = 24, color = 'currentColor' }) => { return ( <img src={${"{constantName}"}} alt="{fileName}" className={className} width={size} height={size} style={{ color }} /> ); };`, inlineTemplate: `// Inline SVG for {fileName} // Note: Replace this comment with actual SVG content from {filePath}`, }, vue: { framework: "vue", importTemplate: "import {constantName} from '../assets/images';", usageTemplate: `<img :src="{constantName}" alt="{fileName}" />`, componentTemplate: `<template> <img :src="{constantName}" :alt="alt || '{fileName}'" :class="className" :width="size" :height="size" :style="{ color }" /> </template> <script setup lang="ts"> import {constantName} from '../assets/images'; interface Props { className?: string; size?: number; color?: string; alt?: string; } withDefaults(defineProps<Props>(), { size: 24, color: 'currentColor', alt: '{fileName}' }); </script>`, inlineTemplate: `<!-- Inline SVG for {fileName} --> <!-- Note: Replace this comment with actual SVG content from {filePath} -->`, }, html: { framework: "html", importTemplate: "// Import {constantName} from '{filePath}'", usageTemplate: `<img src="{filePath}" alt="{fileName}" />`, inlineTemplate: `<!-- Inline SVG for {fileName} --> <!-- Note: Replace this comment with actual SVG content from {filePath} -->`, }, angular: { framework: "angular", importTemplate: "// Import path: {filePath}", usageTemplate: `<img [src]="'{filePath}'" alt="{fileName}" />`, componentTemplate: `import { Component, Input } from '@angular/core'; @Component({ selector: 'app-{fileName}-icon', template: \` <img [src]="imagePath" [alt]="alt" [class]="className" [style.width.px]="size" [style.height.px]="size" [style.color]="color" /> \` }) export class {componentName}Component { @Input() className?: string; @Input() size: number = 24; @Input() color: string = 'currentColor'; @Input() alt: string = '{fileName}'; imagePath = '{filePath}'; }`, inlineTemplate: `<!-- Inline SVG for {fileName} --> <!-- Note: Replace this comment with actual SVG content from {filePath} -->`, }, svelte: { framework: "svelte", importTemplate: "import {constantName} from '../assets/images';", usageTemplate: `<img src={${"{constantName}"}} alt="{fileName}" />`, componentTemplate: `<script lang="ts"> import {constantName} from '../assets/images'; export let className: string = ''; export let size: number = 24; export let color: string = 'currentColor'; export let alt: string = '{fileName}'; </script> <img src={${"{constantName}"}} {alt} class={className} width={size} height={size} style="color: {color}" />`, inlineTemplate: `<!-- Inline SVG for {fileName} --> <!-- Note: Replace this comment with actual SVG content from {filePath} -->`, }, }; return templates[framework]; } } exports.TypeDefinitionGenerator = TypeDefinitionGenerator; //# sourceMappingURL=CodeGenerator.js.map