Contributing
Thank you for considering contributing to LaraSVG! This guide will help you get started.
Development Setup
Prerequisites
- PHP 8.4+
- Composer
- (Optional) Resvg — for running integration tests
- (Optional) Inkscape 1.0+ — for running integration tests
Installation
bash
git clone https://github.com/laratusk/larasvg.git
cd larasvg
composer installQuality Tools
This project uses four quality tools that must all pass before code can be merged. Run them all at once:
bash
composer qualityPint (Code Style)
Laravel Pint with the Laravel preset:
bash
# Check for style issues
composer lint:test
# Auto-fix style issues
composer lintRector (Automated Refactoring)
Rector enforces modern PHP patterns:
bash
# Preview changes (dry run)
composer rector:test
# Apply changes
composer rectorPHPStan (Static Analysis)
Larastan runs at level 6:
bash
composer analysePHPUnit (Tests)
bash
# Run all tests
composer test
# Unit tests only
composer test:unit
# Feature tests only
composer test:feature
# Integration tests (requires binaries)
composer test:integrationTest Structure
| Suite | Directory | Description |
|---|---|---|
| Unit | tests/Unit/ | Tests individual classes in isolation. No external processes. |
| Feature | tests/Feature/ | Tests package features using Process::fake(). No binaries needed. |
| Integration | tests/Integration/ | Runs real conversion commands. Requires resvg/inkscape installed. |
Writing Tests
- Extend
Laratusk\Larasvg\Tests\TestCasefor all tests - Use
Process::fake()in unit and feature tests - Use the
#[Test]attribute instead oftest_method prefixes - Use
$this->createTempSvg()helper from TestCase for temporary SVG files - Clean up temp files in
tearDown()
php
<?php
namespace Laratusk\Larasvg\Tests\Unit;
use Laratusk\Larasvg\Tests\TestCase;
use PHPUnit\Framework\Attributes\Test;
class MyNewTest extends TestCase
{
#[Test]
public function it_does_something(): void
{
// Arrange, Act, Assert
}
}Architecture Overview
src/
├── Contracts/
│ └── Provider.php # Interface for all converters
├── Converters/
│ ├── AbstractConverter.php # Shared converter logic
│ ├── InkscapeConverter.php # Inkscape CLI implementation
│ └── ResvgConverter.php # Resvg CLI implementation
├── Exceptions/
│ └── SvgConverterException.php # Custom exception with process details
├── Facades/
│ └── SvgConverter.php # Laravel facade
├── Commands/
│ └── SetupCommand.php # artisan larasvg:setup
├── SvgConverterManager.php # Manager (provider selection, file opening)
└── SvgConverterServiceProvider.phpKey Design Decisions
- Manager pattern —
SvgConverterManagerselects the provider and creates converter instances - Abstract base class —
AbstractConverterhandles shared logic (formats, dimensions, background, temp files, execution) - Provider-specific subclasses — Override CLI option names and add provider-specific methods
- Laravel Process facade — All CLI execution goes through
Process::run()for testability
Adding a New Provider
- Create a new converter class extending
AbstractConverter - Implement
providerName(),supportedFormats(),version(),buildCommand(), andapplyExportOptions() - Override option name methods (
widthOption(), etc.) if the CLI uses different flag names - Register the provider in
SvgConverterManager::createConverter() - Add unit, feature, and integration tests
Pull Request Workflow
- Fork the repository and create a feature branch from
main - Write code following the existing patterns and conventions
- Run the quality pipeline before committing:bash
composer quality - Commit with a clear, descriptive message
- Push your branch and open a pull request
PR Checklist
- [ ] All quality checks pass (
composer quality) - [ ] New features include tests
- [ ] PHPDoc types are added for new public methods
- [ ] No breaking changes to the public API (or clearly documented if intentional)
Reporting Issues
When reporting bugs, please include:
- PHP version (
php -v) - Laravel version
- Provider and version (
resvg --versionorinkscape --version) - Minimal reproduction steps
- Full error message and stack trace
License
By contributing, you agree that your contributions will be licensed under the MIT License.