docs: Split documentation into separate files

- Move development details to DEVELOPMENT.md
- Move contributing guidelines to CONTRIBUTING.md
- Add LICENSE file with MIT license
- Add CONTRIBUTORS.md for attribution
- Update README.md to focus on user-facing information
- Improve documentation structure and navigation
This commit is contained in:
Alvaro Soliverez 2025-10-04 12:33:59 -03:00
parent 8362ebe44b
commit 37e9bc2dc1
5 changed files with 826 additions and 122 deletions

358
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,358 @@
# Contributing to CalDAV Calendar Synchronizer
Thank you for your interest in contributing to the CalDAV Calendar Synchronizer! This document provides guidelines and information for contributors.
## Getting Started
### Prerequisites
- Rust 1.70 or newer
- Git
- Basic familiarity with CalDAV protocol
- Understanding of async/await in Rust
### Development Setup
1. **Fork and Clone**
```bash
# Fork the repository on your Forgejo instance
git clone ssh://git@gitea.soliverez.com.ar/YOUR_USERNAME/caldavpuller.git
cd caldavpuller
# Add upstream remote
git remote add upstream ssh://git@gitea.soliverez.com.ar/alvaro/caldavpuller.git
```
2. **Install Development Tools**
```bash
# Install Rust toolchain
rustup update stable
rustup component add rustfmt clippy rust-analyzer
# Verify installation
cargo --version
rustfmt --version
clippy --version
```
3. **Build and Test**
```bash
# Build the project
cargo build
# Run tests
cargo test
# Check formatting
cargo fmt --check
# Run linter
cargo clippy -- -D warnings
```
## Development Workflow
### 1. **Create a Branch**
```bash
# Sync with upstream
git fetch upstream
git checkout main
git merge upstream/main
# Create feature branch
git checkout -b feature/your-feature-name
# or
git checkout -b fix/your-fix-name
```
### 2. **Make Changes**
- Follow the existing code style
- Add tests for new functionality
- Update documentation as needed
- Ensure all tests pass
### 3. **Commit Changes**
Use clear, descriptive commit messages:
```bash
# Good commit message
git commit -m "feat: Add support for calendar color filtering
- Add color field to CalendarInfo struct
- Implement color-based filtering in CalendarFilter
- Add configuration option for color preferences
- Add unit tests for color filtering logic"
# Another good example
git commit -m "fix: Handle timezone parsing errors gracefully
- Add proper error handling for unknown timezone identifiers
- Return meaningful error messages to users
- Add integration tests for timezone edge cases"
```
### 4. **Submit Pull Request**
```bash
# Push to your fork
git push origin feature/your-feature-name
# Create pull request on Forgejo
# Provide clear description of changes and testing done
```
## Code Style and Standards
### 1. **Formatting**
Use `rustfmt` with default settings:
```bash
cargo fmt
```
### 2. **Linting**
All code must pass `clippy` without warnings:
```bash
cargo clippy -- -D warnings
```
### 3. **Documentation**
- Document all public APIs with `///` comments
- Include examples for complex functionality
- Update README and other documentation as needed
```rust
/// Filters calendars based on user-defined criteria.
///
/// # Examples
///
/// ```
/// use caldav_sync::CalendarFilter;
///
/// let filter = CalendarFilter::new()
/// .with_selected_calendars(vec!["Work".to_string()]);
///
/// assert!(filter.should_import_calendar("Work"));
/// assert!(!filter.should_import_calendar("Personal"));
/// ```
pub struct CalendarFilter {
// ...
}
```
### 4. **Error Handling**
- Use `Result<T, CalDavError>` for fallible operations
- Provide meaningful error context
- Handle errors gracefully at the UI layer
```rust
pub async fn sync_calendars(&mut self) -> CalDavResult<SyncStats> {
let calendars = self.discover_calendars().await
.context("Failed to discover calendars")?;
// ... rest of implementation
}
```
### 5. **Testing**
Write comprehensive tests:
```rust
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_calendar_filtering() {
let filter = CalendarFilter::new()
.with_selected_calendars(vec!["Work".to_string()]);
assert!(filter.should_import_calendar("Work"));
assert!(!filter.should_import_calendar("Personal"));
}
}
```
## Testing
### 1. **Unit Tests**
Test individual components in isolation:
```bash
cargo test --lib
```
### 2. **Integration Tests**
Test component interactions:
```bash
cargo test --test integration_tests
```
### 3. **Manual Testing**
Test with real CalDAV servers:
```bash
# Build and run with debug logging
cargo build
./target/debug/caldav-sync --debug --list-events
```
### 4. **Test Coverage**
Aim for high test coverage, especially for:
- Configuration parsing
- Error handling paths
- Calendar filtering logic
- Timezone conversions
## Types of Contributions
### 1. **Bug Fixes**
- Check existing issues for bug reports
- Create minimal reproduction case
- Add tests that fail before the fix
- Fix the issue and ensure tests pass
### 2. **New Features**
- Open issue for discussion first
- Design the feature interface
- Implement with tests
- Update documentation
### 3. **Documentation**
- Improve README and guides
- Add code examples
- Fix typos and clarity issues
- Translate documentation if possible
### 4. **Performance Improvements**
- Profile existing code
- Identify bottlenecks
- Implement optimizations
- Add benchmarks for verification
## Areas Needing Help
### 1. **Enhanced CalDAV Support**
- Better support for CalDAV extensions
- Handling of recurring events
- Support for attachments and attendees
### 2. **User Experience**
- Interactive configuration wizard
- Progress indicators for long operations
- Better error messages and recovery
### 3. **Testing Infrastructure**
- Mock CalDAV server for testing
- Automated testing in CI/CD
- Performance benchmarks
### 4. **Documentation**
- User guides for different platforms
- API documentation
- Troubleshooting guides
## Code Review Process
### 1. **Self-Review**
Before submitting, review your own changes:
- Code follows project style
- Tests are comprehensive
- Documentation is updated
- No debug code or TODOs left
### 2. **Review Criteria**
Maintainers will review for:
- Correctness and safety
- Performance implications
- User experience impact
- Code maintainability
### 3. **Feedback**
Be prepared to:
- Answer questions about your changes
- Make requested modifications
- Discuss alternative approaches
- Update tests based on feedback
## Release Process
### 1. **Version Management**
- Follow semantic versioning (MAJOR.MINOR.PATCH)
- Update version in `Cargo.toml`
- Create git tag for releases
### 2. **Changelog**
Maintain `CHANGELOG.md` with:
- New features
- Bug fixes
- Breaking changes
- Migration notes
### 3. **Release Checklist**
- [ ] All tests pass
- [ ] Documentation updated
- [ ] Version numbers updated
- [ ] Changelog updated
- [ ] Release tag created
- [ ] Release artifacts built
## Support and Communication
### 1. **Issues and Questions**
- Use GitHub issues for bug reports and feature requests
- Check existing issues before creating new ones
- Provide clear, reproducible examples
### 2. **Discussions**
- Use discussions for general questions
- Share ideas and suggestions
- Ask for help with development
### 3. **Code of Conduct**
Be respectful and constructive:
- Welcome newcomers and help them learn
- Assume good faith in interactions
- Focus on what is best for the community
- Show empathy towards other community members
## Recognition
Contributors are recognized in:
- `CONTRIBUTORS.md` file
- Release notes
- Git commit history
- Project documentation
Thank you for contributing to the CalDAV Calendar Synchronizer! Your contributions help make this project better for everyone.

17
CONTRIBUTORS.md Normal file
View file

@ -0,0 +1,17 @@
# Contributors
This project exists thanks to all the people who contribute.
## Lead Developer
- **Alvaro Soliverez** - *Project creator and maintainer*
## Development Setup
For information on how to contribute to this project, please see [CONTRIBUTING.md](CONTRIBUTING.md).
## Acknowledgments
- The Rust community for excellent tools and libraries
- The CalDAV protocol developers and maintainers
- All users who provide feedback and bug reports

416
DEVELOPMENT.md Normal file
View file

@ -0,0 +1,416 @@
# Development Guide
This document provides comprehensive information about the design, architecture, and development of the CalDAV Calendar Synchronizer.
## Architecture Overview
The application is built with a modular architecture using Rust's strong type system and async capabilities.
### Core Components
#### 1. **Configuration System** (`src/config.rs`)
- **Purpose**: Manage configuration from files, environment variables, and CLI arguments
- **Features**:
- TOML-based configuration files
- Environment variable support
- Command-line argument overrides
- Configuration validation
- **Key Types**: `Config`, `ServerConfig`, `CalendarConfig`, `SyncConfig`
#### 2. **CalDAV Client** (`src/caldav_client.rs`)
- **Purpose**: Handle CalDAV protocol operations with Zoho and Nextcloud
- **Features**:
- HTTP client with authentication
- Calendar discovery via PROPFIND
- Event retrieval via REPORT requests
- Event creation via PUT requests
- **Key Types**: `CalDavClient`, `CalendarInfo`, `CalDavEventInfo`
#### 3. **Event Model** (`src/event.rs`)
- **Purpose**: Represent calendar events and handle parsing
- **Features**:
- iCalendar data parsing
- Timezone-aware datetime handling
- Event filtering and validation
- **Key Types**: `Event`, `EventBuilder`, `EventFilter`
#### 4. **Timezone Handler** (`src/timezone.rs`)
- **Purpose**: Manage timezone conversions and datetime operations
- **Features**:
- Convert between different timezones
- Parse timezone information from iCalendar data
- Handle DST transitions
- **Key Types**: `TimezoneHandler`, `TimeZoneInfo`
#### 5. **Calendar Filter** (`src/calendar_filter.rs`)
- **Purpose**: Filter calendars and events based on user criteria
- **Features**:
- Calendar name filtering
- Regex pattern matching
- Event date range filtering
- **Key Types**: `CalendarFilter`, `FilterRule`, `EventFilter`
#### 6. **Sync Engine** (`src/sync.rs`)
- **Purpose**: Coordinate the synchronization process
- **Features**:
- Pull events from Zoho
- Push events to Nextcloud
- Conflict resolution
- Progress tracking
- **Key Types**: `SyncEngine`, `SyncResult`, `SyncStats`
#### 7. **Error Handling** (`src/error.rs`)
- **Purpose**: Comprehensive error management
- **Features**:
- Custom error types
- Error context and chaining
- User-friendly error messages
- **Key Types**: `CalDavError`, `CalDavResult`
## Design Decisions
### 1. **Selective Calendar Import**
The application allows users to select specific Zoho calendars to import from, consolidating all events into a single Nextcloud calendar. This design choice:
- **Reduces complexity** compared to bidirectional sync
- **Provides clear data flow** (Zoho → Nextcloud)
- **Minimizes sync conflicts**
- **Matches user requirements** exactly
### 2. **Timezone Handling**
All events are converted to UTC internally for consistency, while preserving original timezone information:
```rust
pub struct Event {
pub id: String,
pub summary: String,
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
pub original_timezone: Option<String>,
pub source_calendar: String,
}
```
### 3. **Configuration Hierarchy**
Configuration is loaded in priority order:
1. **Command line arguments** (highest priority)
2. **User config file** (`config/config.toml`)
3. **Default config file** (`config/default.toml`)
4. **Environment variables**
5. **Hardcoded defaults** (lowest priority)
### 4. **Error Handling Strategy**
Uses `thiserror` for custom error types and `anyhow` for error propagation:
```rust
#[derive(Error, Debug)]
pub enum CalDavError {
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
#[error("Configuration error: {0}")]
Config(String),
#[error("Calendar not found: {0}")]
CalendarNotFound(String),
// ... more error variants
}
```
## Data Flow
### 1. **Application Startup**
```
1. Load CLI arguments
2. Load configuration files
3. Apply environment variables
4. Validate configuration
5. Initialize logging
6. Create CalDAV clients
```
### 2. **Calendar Discovery**
```
1. Connect to Zoho CalDAV server
2. Authenticate with app password
3. Send PROPFIND request to discover calendars
4. Parse calendar list and metadata
5. Apply user filters to select calendars
```
### 3. **Event Synchronization**
```
1. Query selected Zoho calendars for events (next week)
2. Parse iCalendar data into Event objects
3. Convert timestamps to UTC with timezone preservation
4. Apply event filters (duration, status, patterns)
5. Connect to Nextcloud CalDAV server
6. Create target calendar if needed
7. Upload events to Nextcloud calendar
8. Report sync statistics
```
## Key Algorithms
### 1. **Calendar Filtering**
```rust
impl CalendarFilter {
pub fn should_import_calendar(&self, calendar_name: &str) -> bool {
// Check exact matches
if self.selected_names.contains(&calendar_name.to_string()) {
return true;
}
// Check regex patterns
for pattern in &self.regex_patterns {
if pattern.is_match(calendar_name) {
return true;
}
}
false
}
}
```
### 2. **Timezone Conversion**
```rust
impl TimezoneHandler {
pub fn convert_to_utc(&self, dt: DateTime<FixedOffset>, timezone: &str) -> CalDavResult<DateTime<Utc>> {
let tz = self.get_timezone(timezone)?;
let local_dt = dt.with_timezone(&tz);
Ok(local_dt.with_timezone(&Utc))
}
}
```
### 3. **Event Processing**
```rust
impl SyncEngine {
pub async fn sync_calendar(&mut self, calendar: &CalendarInfo) -> CalDavResult<SyncResult> {
// 1. Fetch events from Zoho
let zoho_events = self.fetch_zoho_events(calendar).await?;
// 2. Filter and process events
let processed_events = self.process_events(zoho_events)?;
// 3. Upload to Nextcloud
let upload_results = self.upload_to_nextcloud(processed_events).await?;
// 4. Return sync statistics
Ok(SyncResult::from_upload_results(upload_results))
}
}
```
## Configuration Schema
### Complete Configuration Structure
```toml
# Zoho Configuration (Source)
[zoho]
server_url = "https://caldav.zoho.com/caldav"
username = "your-zoho-email@domain.com"
password = "your-zoho-app-password"
selected_calendars = ["Work Calendar", "Personal Calendar"]
# Nextcloud Configuration (Target)
[nextcloud]
server_url = "https://your-nextcloud-domain.com"
username = "your-nextcloud-username"
password = "your-nextcloud-app-password"
target_calendar = "Imported-Zoho-Events"
create_if_missing = true
# General Settings
[server]
timeout = 30
[calendar]
color = "#3174ad"
timezone = "UTC"
[sync]
interval = 300
sync_on_startup = true
weeks_ahead = 1
dry_run = false
# Optional Filtering
[filters]
min_duration_minutes = 5
max_duration_hours = 24
exclude_patterns = ["Cancelled:", "BLOCKED"]
include_status = ["confirmed", "tentative"]
exclude_status = ["cancelled"]
```
## Dependencies and External Libraries
### Core Dependencies
```toml
[dependencies]
tokio = { version = "1.0", features = ["full"] } # Async runtime
reqwest = { version = "0.11", features = ["json", "xml"] } # HTTP client
serde = { version = "1.0", features = ["derive"] } # Serialization
chrono = { version = "0.4", features = ["serde"] } # Date/time
chrono-tz = "0.8" # Timezone support
quick-xml = "0.28" # XML parsing
thiserror = "1.0" # Error handling
anyhow = "1.0" # Error propagation
config = "0.13" # Configuration
clap = { version = "4.0", features = ["derive"] } # CLI
tracing = "0.1" # Logging
tracing-subscriber = "0.3" # Log formatting
toml = "0.8" # TOML parsing
```
### Optional Dependencies for Future Features
```toml
# For enhanced XML handling
serde_xml_rs = "0.6"
# For better HTTP client customization
http = "0.2"
# For async file operations
tokio-util = "0.7"
# For better error formatting
color-eyre = "0.6"
```
## Testing Strategy
### 1. **Unit Tests**
- Individual module functionality
- Configuration parsing and validation
- Event parsing and timezone conversion
- Error handling paths
### 2. **Integration Tests**
- End-to-end CalDAV operations
- Configuration loading from files
- CLI argument processing
- HTTP client behavior
### 3. **Mock Testing**
- Mock CalDAV server responses
- Test error conditions without real servers
- Validate retry logic and timeout handling
## Performance Considerations
### 1. **Async Operations**
All network operations are async to prevent blocking:
```rust
pub async fn fetch_events(&self, calendar: &CalendarInfo) -> CalDavResult<Vec<Event>> {
let response = self.client
.request(reqwest::Method::REPORT, &calendar.url)
.body(report_body)
.send()
.await?;
// Process response...
}
```
### 2. **Memory Management**
- Stream processing for large calendar responses
- Efficient string handling with `Cow<str>` where appropriate
- Clear lifecycle management for HTTP connections
### 3. **Configuration Caching**
- Cache parsed timezone information
- Reuse HTTP connections where possible
- Validate configuration once at startup
## Security Considerations
### 1. **Authentication**
- Support for app-specific passwords only
- Never log authentication credentials
- Secure storage of sensitive configuration
### 2. **Network Security**
- Enforce HTTPS by default
- SSL certificate validation
- Custom CA certificate support
### 3. **Data Privacy**
- Minimal data collection (only required event fields)
- Optional debug logging with sensitive data filtering
- Clear data retention policies
## Future Enhancements
### 1. **Enhanced Filtering**
- Advanced regex patterns
- Calendar color-based filtering
- Attendee-based filtering
### 2. **Bidirectional Sync**
- Two-way synchronization with conflict resolution
- Event modification tracking
- Deletion synchronization
### 3. **Performance Optimizations**
- Parallel calendar processing
- Incremental sync with change detection
- Local caching and offline mode
### 4. **User Experience**
- Interactive configuration wizard
- Web-based status dashboard
- Real-time sync notifications
## Build and Development
### 1. **Development Setup**
```bash
# Clone repository
git clone ssh://git@gitea.soliverez.com.ar/alvaro/caldavpuller.git
cd caldavpuller
# Install Rust toolchain
rustup update stable
rustup component add rustfmt clippy
# Build in development mode
cargo build
# Run tests
cargo test
# Check formatting
cargo fmt --check
# Run linter
cargo clippy -- -D warnings
```
### 2. **Release Build**
```bash
# Build optimized release
cargo build --release
# Create distribution archive
tar -czf caldav-sync-${VERSION}-${TARGET}.tar.gz \
-C target/release caldav-sync \
-C ../config example.toml \
-C .. README.md LICENSE
```
### 3. **Testing with Mock Servers**
For testing without real CalDAV servers, use the mock server setup:
```bash
# Start mock CalDAV server
cargo run --bin mock-server
# Run integration tests against mock server
cargo test --test integration_tests
```
This architecture provides a solid foundation for the CalDAV synchronization tool while maintaining flexibility for future enhancements.

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Alvaro Soliverez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

136
README.md
View file

@ -14,18 +14,18 @@ A Rust-based command-line tool that synchronizes calendar events between Zoho Ca
## Quick Start ## Quick Start
### 1. Prerequisites ### Prerequisites
- Rust 1.70+ (for building from source) - Rust 1.70+ (for building from source)
- Zoho account with CalDAV access - Zoho account with CalDAV access
- Nextcloud instance with CalDAV enabled - Nextcloud instance with CalDAV enabled
- App-specific passwords for both services (recommended) - App-specific passwords for both services (recommended)
### 2. Installation ### Installation
```bash ```bash
# Clone the repository # Clone the repository
git clone <repository-url> git clone ssh://git@gitea.soliverez.com.ar/alvaro/caldavpuller.git
cd caldavpuller cd caldavpuller
# Build the project # Build the project
@ -34,7 +34,7 @@ cargo build --release
# The binary will be at target/release/caldav-sync # The binary will be at target/release/caldav-sync
``` ```
### 3. Configuration ### Configuration
Copy the example configuration file: Copy the example configuration file:
@ -63,7 +63,7 @@ target_calendar = "Imported-Zoho-Events"
create_if_missing = true create_if_missing = true
``` ```
### 4. First Run ### First Run
Test the configuration with a dry run: Test the configuration with a dry run:
@ -77,35 +77,6 @@ Perform a one-time sync:
./target/release/caldav-sync --once ./target/release/caldav-sync --once
``` ```
## Configuration Details
### Zoho Setup
1. **Enable CalDAV in Zoho**:
- Go to Zoho Mail Settings → CalDAV
- Enable CalDAV access
- Generate an app-specific password
2. **Find Calendar Names**:
```bash
./target/release/caldav-sync --list-events --debug
```
This will show all available calendars.
### Nextcloud Setup
1. **Enable CalDAV**:
- Usually enabled by default
- Access at `https://your-domain.com/remote.php/dav/`
2. **Generate App Password**:
- Go to Settings → Security → App passwords
- Create a new app password for the sync tool
3. **Target Calendar**:
- The tool can automatically create the target calendar
- Or create it manually in Nextcloud first
## Usage ## Usage
### Command Line Options ### Command Line Options
@ -149,36 +120,7 @@ Options:
caldav-sync --username "user@example.com" --password "app-password" --once caldav-sync --username "user@example.com" --password "app-password" --once
``` ```
## Configuration Reference ## Configuration
### Complete Configuration Example
```toml
[server]
url = "https://caldav.zoho.com/caldav"
username = "your-email@domain.com"
password = "your-app-password"
timeout = 30
[calendar]
name = "Work Calendar"
color = "#4285F4"
[sync]
sync_interval = 300
sync_on_startup = true
weeks_ahead = 1
dry_run = false
[filters]
exclude_patterns = ["Cancelled:", "BLOCKED"]
min_duration_minutes = 5
max_duration_hours = 24
[logging]
level = "info"
file = "caldav-sync.log"
```
### Environment Variables ### Environment Variables
@ -193,6 +135,10 @@ export CALDAV_CALENDAR="Work Calendar"
./target/release/caldav-sync ./target/release/caldav-sync
``` ```
### Complete Configuration Example
See `config/example.toml` for a comprehensive configuration example with all available options.
## Security Considerations ## Security Considerations
1. **Use App Passwords**: Never use your main account password 1. **Use App Passwords**: Never use your main account password
@ -233,65 +179,11 @@ caldav-sync --debug --list-events
This will show detailed HTTP requests, responses, and processing steps. This will show detailed HTTP requests, responses, and processing steps.
## Development ## More Information
### Building from Source - **Development & Design**: See [DEVELOPMENT.md](DEVELOPMENT.md)
- **Contributing**: See [CONTRIBUTING.md](CONTRIBUTING.md)
```bash - **License**: See [LICENSE](LICENSE)
# Clone the repository
git clone <repository-url>
cd caldavpuller
# Build in debug mode
cargo build
# Build in release mode
cargo build --release
# Run tests
cargo test
# Check code formatting
cargo fmt --check
# Run linter
cargo clippy
```
### Project Structure
```
caldavpuller/
├── src/
│ ├── main.rs # CLI interface and entry point
│ ├── lib.rs # Library interface
│ ├── config.rs # Configuration management
│ ├── caldav_client.rs # CalDAV HTTP client
│ ├── event.rs # Event data structures
│ ├── timezone.rs # Timezone handling
│ ├── calendar_filter.rs # Calendar filtering logic
│ ├── sync.rs # Synchronization engine
│ └── error.rs # Error types and handling
├── config/
│ ├── default.toml # Default configuration
│ └── example.toml # Example configuration
├── tests/
│ └── integration_tests.rs # Integration tests
├── Cargo.toml # Rust project configuration
└── README.md # This file
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Support ## Support