svgfusion-core
Version:
Core engine and utilities for SVGFusion - the foundation library that powers SVG to component conversion.
396 lines (385 loc) • 11 kB
TypeScript
export { ColorInfo, extractColors, extractColorsWithElementMapping, generateColorProps, generateDefaultColors, replaceColorsWithProps, replaceCurrentColorWithVariables } from 'svgfusion-utils';
/**
* SVG parsing and AST (Abstract Syntax Tree) generation
* Industry standard approach for parsing SVG content into a structured format
*/
interface SVGElement {
tag: string;
attributes: Record<string, string>;
children: SVGElement[];
content?: string;
}
interface SVGAst {
root: SVGElement;
viewBox?: string;
width?: string;
height?: string;
namespace?: string;
}
interface ParsedColor {
value: string;
type: 'fill' | 'stroke' | 'stop-color';
element: SVGElement;
attribute: string;
}
/**
* Parse SVG content into an Abstract Syntax Tree
*/
declare class SVGParser {
/**
* Parse SVG string into structured AST
*/
parse(svgContent: string): SVGAst;
/**
* Extract all colors from the SVG AST
*/
extractColors(ast: SVGAst): ParsedColor[];
/**
* Clean SVG content by removing XML declarations and comments
*/
private cleanSvgContent;
/**
* Parse a single SVG element using proper XML parser
*/
private parseElement;
/**
* Convert DOM element to SVGElement (works for both browser DOMParser and jsdom)
*/
private convertDOMToSVGElement;
/**
* Fallback: Parse SVG element using regex (original implementation)
*/
private parseElementWithRegex;
/**
* Parse attributes from an element string
*/
private parseAttributes;
/**
* Parse child elements from SVG content
*/
private parseChildren;
/**
* Parse nested elements (for complex SVGs with groups, etc.)
*/
private parseNestedElements;
/**
* Traverse all elements in the AST
*/
private traverseElements;
/**
* Preserve proper case for SVG elements
*/
private preserveSvgTagCase;
/**
* Check if a color value is valid and should be processed
*/
private isValidColor;
}
/**
* Core transformation engine for SVG processing
* Handles optimization, color manipulation, and feature application
*/
interface TransformationOptions {
optimize?: boolean;
splitColors?: boolean;
splitStrokeWidths?: boolean;
fixedStrokeWidth?: boolean;
normalizeFillStroke?: boolean;
accessibility?: boolean;
removeComments?: boolean;
removeDuplicates?: boolean;
minifyPaths?: boolean;
}
interface StrokeWidthMapping {
originalStrokeWidth: string;
variableName: string;
}
interface ColorMapping {
originalColor: string;
variableName: string;
type: 'fill' | 'stroke' | 'stop-color';
}
interface TransformationResult {
ast: SVGAst;
colorMappings: ColorMapping[];
strokeWidthMappings: StrokeWidthMapping[];
metadata: {
originalColors: string[];
originalStrokeWidths: string[];
optimizationApplied: boolean;
features: string[];
hasClassAttributes: boolean;
};
}
/**
* Core SVG transformation engine
*/
declare class SVGTransformer {
/**
* Transform SVG AST based on provided options
*/
transform(ast: SVGAst, options?: TransformationOptions): TransformationResult;
/**
* Apply color splitting transformation
*/
private applySplitColors;
/**
* Apply fixed stroke width transformation
*/
private applyFixedStrokeWidth;
/**
* Apply accessibility enhancements
*/
private applyAccessibility;
/**
* Apply fill/stroke normalization
*/
private applyFillStrokeNormalization;
/**
* Apply various optimizations
*/
private applyOptimizations;
/**
* Remove duplicate elements (same tag and attributes)
*/
private removeDuplicateElements;
/**
* Minify path data
*/
private minifyPaths;
/**
* Remove empty groups and unnecessary nesting
*/
private removeEmptyGroups;
/**
* Traverse all elements in the AST
*/
private traverseElements;
/**
* Check if a color value is valid
*/
private isValidColor;
/**
* Deep clone AST to avoid mutations
*/
private deepCloneAst;
/**
* Deep clone SVG element
*/
private deepCloneElement;
/**
* Check if the SVG has any class attributes in its elements
*/
private hasClassAttributes;
/**
* Apply stroke width splitting transformation
*/
private applySplitStrokeWidths;
}
/**
* Abstract component generator base class
* Provides common functionality for all component generators
*/
interface GeneratorOptions {
typescript?: boolean;
memo?: boolean;
forwardRef?: boolean;
exportDefault?: boolean;
componentName?: string;
prefix?: string;
suffix?: string;
includeTypes?: boolean;
}
interface ComponentResult {
code: string;
filename: string;
componentName: string;
dependencies: string[];
}
/**
* Abstract base class for component generators
*/
declare abstract class ComponentGenerator {
protected options: Required<GeneratorOptions>;
constructor(options?: GeneratorOptions);
/**
* Generate component code from transformation result
*/
abstract generate(result: TransformationResult): ComponentResult | Promise<ComponentResult>;
/**
* Convert SVG AST to JSX string
*/
protected astToJsx(ast: SVGAst): string;
/**
* Convert SVG element to JSX
*/
protected elementToJsx(element: SVGElement, depth?: number): string;
/**
* Convert attributes object to JSX attributes array
*/
protected attributesToJsx(attributes: Record<string, string>): string[];
/**
* Convert HTML attribute names to JSX equivalents
*/
protected convertAttributeName(name: string): string;
/**
* Generate color props interface/type definitions
*/
protected generateColorProps(colorMappings: ColorMapping[], includeClassProps?: boolean): string;
/**
* Generate default props for colors
*/
protected generateColorDefaults(colorMappings: ColorMapping[]): string;
/**
* Generate stroke width props interface/type definitions
*/
protected generateStrokeWidthProps(strokeWidthMappings: StrokeWidthMapping[], includeClassProps?: boolean): string;
/**
* Generate default props for stroke widths
*/
protected generateStrokeWidthDefaults(strokeWidthMappings: StrokeWidthMapping[]): string;
/**
* Generate component name from options
*/
protected getComponentName(): string;
/**
* Generate filename with appropriate extension
*/
protected generateFilename(componentName: string, extension: string): string;
/**
* Sanitize component name to be valid JavaScript identifier
*/
protected sanitizeComponentName(name: string): string;
}
/**
* Main SVGFusion engine
* Orchestrates parsing, transformation, and code generation
*/
interface SVGFusionOptions {
framework: 'react' | 'vue';
transformation?: TransformationOptions;
generator?: GeneratorOptions;
}
interface ConversionResult$1 {
code: string;
filename: string;
componentName: string;
dependencies: string[];
metadata: {
originalColors: string[];
originalStrokeWidths: string[];
optimizationApplied: boolean;
features: string[];
};
}
/**
* Main SVGFusion engine
*/
declare class SVGFusion {
private parser;
private transformer;
/**
* Initialize SVGFusion engine
*/
constructor();
/**
* Extract colors from SVG for preview/analysis
*/
extractColors(svgContent: string): string[];
/**
* Validate SVG content
*/
validate(svgContent: string): {
valid: boolean;
errors: string[];
};
/**
* Convert SVG content to component code
*/
convert(svgContent: string, options: SVGFusionOptions, generatorConstructor: new (options: GeneratorOptions) => any): Promise<ConversionResult$1>;
}
interface ConversionOptions {
name?: string;
prefix?: string;
suffix?: string;
optimize?: boolean;
typescript?: boolean;
format?: 'esm' | 'cjs';
splitColors?: boolean;
splitStrokeWidths?: boolean;
fixedStrokeWidth?: boolean;
normalizeFillStroke?: boolean;
accessibility?: boolean;
removeComments?: boolean;
removeDuplicates?: boolean;
minifyPaths?: boolean;
isFixedStrokeWidth?: boolean;
}
interface ReactConversionOptions extends ConversionOptions {
memo?: boolean;
ref?: boolean;
titleProp?: boolean;
descProp?: boolean;
icon?: boolean;
dimensions?: boolean;
replaceAttrValues?: Record<string, string>;
svgProps?: Record<string, string>;
expandProps?: boolean | 'start' | 'end';
nativeProps?: boolean;
ariaLabelledBy?: boolean;
ariaHidden?: boolean;
role?: 'img' | 'graphics-document' | 'graphics-symbol' | 'presentation';
}
interface VueConversionOptions extends ConversionOptions {
compositionApi?: boolean;
scriptSetup?: boolean;
props?: boolean;
dimensions?: boolean;
replaceAttrValues?: Record<string, string>;
}
interface ConversionResult {
code: string;
filename: string;
componentName: string;
colors?: string[];
}
interface BatchConversionOptions extends ConversionOptions {
inputDir: string;
outputDir: string;
recursive?: boolean;
extensions?: string[];
generateIndex?: boolean;
indexFormat?: 'ts' | 'js';
exportType?: 'named' | 'default';
framework?: Framework;
}
interface BatchConversionResult {
results: ConversionResult[];
errors: ConversionError[];
summary: {
total: number;
successful: number;
failed: number;
};
}
interface ConversionError {
file: string;
error: string;
stack?: string;
}
type Framework = 'react' | 'vue';
interface IndexGenerationOptions {
format: 'ts' | 'js';
exportType: 'named' | 'default';
typescript: boolean;
framework?: 'react' | 'vue';
}
/**
* Generate index file content for tree-shaking
*/
declare function generateIndexFile(results: ConversionResult[], options: IndexGenerationOptions): string;
/**
* Generate README content for the generated components
*/
declare function generateReadmeContent(results: ConversionResult[]): string;
export { type BatchConversionOptions, type BatchConversionResult, type ColorMapping, ComponentGenerator, type ComponentResult, type ConversionError, type ConversionOptions, type ConversionResult$1 as ConversionResult, type Framework, type GeneratorOptions, type IndexGenerationOptions, type ParsedColor, type ReactConversionOptions, type SVGAst, type SVGElement, SVGFusion, type SVGFusionOptions, SVGParser, SVGTransformer, type StrokeWidthMapping, type TransformationOptions, type TransformationResult, type VueConversionOptions, generateIndexFile, generateReadmeContent };