Developer Guide¶
{: .no_toc }
APIs, architecture, and contributing to Vexy SVGO
Table of contents¶
{: .no_toc .text-delta }
- TOC
Overview¶
Vexy SVGO is designed for both end-users and developers. This section covers the technical aspects of the project, including APIs, architecture, and how to contribute.
For Developers¶
- π§ Rust API: Use Vexy SVGO as a library in Rust projects
- π WebAssembly: Integrate into web applications and Node.js
- π§© Plugin Development: Create custom optimization plugins
- π€ Contributing: Help improve the project
Architecture Overview¶
Vexy SVGO follows a modular architecture inspired by SVGO but optimized for Rust:
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β β β β β
β Input SVG βββββΆβ Parser βββββΆβ AST β
β β β β β β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β
βΌ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β β β β β
β Optimized SVG ββββββ Stringifier ββββββ Plugin Engine β
β β β β β β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
Core Components¶
- Parser: Converts SVG strings to Abstract Syntax Tree (AST)
- Plugin Engine: Applies optimization plugins to the AST
- Stringifier: Converts optimized AST back to SVG string
- CLI: Command-line interface for end users
Quick Start for Developers¶
1. Use as Rust Library¶
Add to your Cargo.toml
:
[dependencies]
vexy-svgo = { git = "https://github.com/vexyart/vexy-svgo" }
Basic usage:
use vexy_svgo::{optimize, Config};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let svg = r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="red"/>
</svg>"#;
let config = Config::default();
let result = optimize(svg, &config)?;
println!("Original: {} bytes", svg.len());
println!("Optimized: {} bytes", result.data.len());
println!("Reduction: {:.1}%", result.size_reduction);
Ok(())
}
2. WebAssembly Integration¶
// Load the WASM module
import init, { optimize } from './pkg/vexy_svgo_wasm.js';
async function optimizeSvg() {
await init();
const svg = '<svg>...</svg>';
const config = {
multipass: true,
plugins: {
removeComments: true,
removeEmptyAttrs: true
}
};
const result = optimize(svg, config);
console.log('Optimized:', result.data);
}
3. Create Custom Plugin¶
use vexy_svgo_plugin_sdk::{Plugin, PluginMetadata};
use vexy_svgo_core::{ast::Document, visitor::Visitor};
pub struct MyCustomPlugin;
impl Plugin for MyCustomPlugin {
fn metadata(&self) -> PluginMetadata {
PluginMetadata {
name: "myCustomPlugin".to_string(),
description: "My custom optimization".to_string(),
version: "1.0.0".to_string(),
author: Some("Your Name".to_string()),
tags: vec!["custom"],
experimental: false,
}
}
fn optimize(&mut self, document: &mut Document) -> anyhow::Result<()> {
// Your optimization logic here
Ok(())
}
}
Developer Documentation Sections¶
π API Reference
Complete Rust API documentation
Read docs βποΈ Architecture
Deep dive into system design
Read more βπ§© Plugin Development
Create custom optimization plugins
Learn how βπ€ Contributing
Help improve Vexy SVGO
Get started βDevelopment Setup¶
Prerequisites¶
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install additional tools
cargo install wasm-pack # For WebAssembly builds
Build from Source¶
# Clone repository
git clone https://github.com/vexyart/vexy-svgo
cd vexy-svgo
# Build all components
./build.sh all
# Or build specific components
./build.sh native # CLI and library
./build.sh wasm # WebAssembly
./build.sh docs # Documentation
Run Tests¶
# Run all tests
cargo test
# Run specific test suites
cargo test --package vexy-svgo-core
cargo test --package vexy-svgo-cli
# Run benchmarks
cargo bench
API Examples¶
Basic Optimization¶
use vexy_svgo::{optimize, Config};
let svg = "<svg>...</svg>";
let result = optimize(svg, &Config::default())?;
println!("Optimized: {}", result.data);
Custom Configuration¶
use vexy_svgo::{optimize, Config, PluginConfig};
let config = Config {
multipass: true,
plugins: vec![
PluginConfig::Enabled("removeComments".to_string()),
PluginConfig::WithParams {
name: "convertColors".to_string(),
params: serde_json::json!({
"currentColor": true
})
}
],
js2svg: Js2SvgConfig {
pretty: true,
indent: 2,
..Default::default()
},
..Default::default()
};
let result = optimize(svg, &config)?;
Streaming Interface¶
use vexy_svgo::stream::{SvgOptimizer, StreamConfig};
let mut optimizer = SvgOptimizer::new(StreamConfig::default());
// Process large files in chunks
optimizer.write_chunk(svg_chunk_1)?;
optimizer.write_chunk(svg_chunk_2)?;
let result = optimizer.finalize()?;
WebAssembly Development¶
Building WASM Module¶
# Build for web
wasm-pack build crates/wasm --target web --out-dir pkg-web
# Build for Node.js
wasm-pack build crates/wasm --target nodejs --out-dir pkg-node
# Build for bundlers
wasm-pack build crates/wasm --target bundler --out-dir pkg-bundler
Integration Examples¶
React Component¶
import { useEffect, useState } from 'react';
import init, { optimize } from 'vexy-svgo-wasm';
function SvgOptimizer() {
const [wasmReady, setWasmReady] = useState(false);
useEffect(() => {
init().then(() => setWasmReady(true));
}, []);
const optimizeSvg = (svg) => {
if (!wasmReady) return;
return optimize(svg, { multipass: true });
};
// Component implementation...
}
Node.js Script¶
const { optimize } = require('vexy-svgo-wasm');
async function optimizeFiles() {
const fs = require('fs').promises;
const svg = await fs.readFile('input.svg', 'utf8');
const result = optimize(svg, {
plugins: {
removeComments: true,
removeEmptyAttrs: true
}
});
await fs.writeFile('output.svg', result.data);
console.log(`Reduced size by ${result.sizeReduction}%`);
}
Performance Considerations¶
Optimization Tips¶
- Batch Processing: Process multiple files together
- Plugin Selection: Only enable needed plugins
- Memory Management: Use streaming for large files
- Caching: Cache parsed ASTs when processing similar files
Benchmarking¶
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use vexy_svgo::{optimize, Config};
fn benchmark_optimize(c: &mut Criterion) {
let svg = include_str!("../testdata/large.svg");
let config = Config::default();
c.bench_function("optimize large svg", |b| {
b.iter(|| optimize(black_box(svg), black_box(&config)))
});
}
criterion_group!(benches, benchmark_optimize);
criterion_main!(benches);
Getting Help¶
- π Documentation: Continue reading the developer guides
- π Issues: Report bugs on GitHub Issues
- π¬ Discussions: Ask questions in GitHub Discussions
- π§ Contact: Email the maintainers
Ready to dive deeper? Continue to API Reference β