typst-count 0.1.0

Count words and characters in Typst documents
Documentation
# Contributing to typst-count

Thank you for your interest in contributing to typst-count!

We welcome contributions of all kinds: bug reports, feature requests, documentation improvements, and code contributions.

## Table of Contents

- [Code of Conduct]#code-of-conduct
- [Getting Started]#getting-started
- [How to Contribute]#how-to-contribute
- [Development Workflow]#development-workflow
- [Coding Standards]#coding-standards
- [Testing]#testing
- [Pull Request Process]#pull-request-process
- [Release Process]#release-process

## Code of Conduct

This project follows a simple code of conduct: be respectful, be constructive, and help create a welcoming environment for everyone.

## Getting Started

### Prerequisites

- Rust 1.70 or later
- Git
- A GitHub account

### Setting Up Your Development Environment

1. **Fork the repository** on GitHub

2. **Clone your fork**:
   ```bash
   git clone https://github.com/YOUR_USERNAME/typst-count.git
   cd typst-count
   ```

3. **Add the upstream remote**:
   ```bash
   git remote add upstream https://github.com/HollowNumber/typst-count.git
   ```

4. **Build the project**:
   ```bash
   cargo build
   ```

5. **Run the tests**:
   ```bash
   cargo test
   ```

6. **Try the CLI**:
   ```bash
   cargo run -- --help
   ```

## How to Contribute

### Reporting Bugs

Before creating a bug report:
- Check the existing issues to avoid duplicates
- Collect information about your environment (OS, Rust version, etc.)

When filing a bug report, include:
- A clear and descriptive title
- Steps to reproduce the issue
- Expected behavior vs. actual behavior
- Any error messages or logs
- Your environment details (OS, Rust version, typst-count version)
- Sample Typst files if relevant (or minimal reproducible examples)

### Suggesting Features

Feature requests are welcome! Please:
- Check existing issues/PRs to avoid duplicates
- Explain the use case and why it would be valuable
- Provide examples of how the feature would be used
- Consider whether it fits the scope of the project

### Improving Documentation

Documentation improvements are always appreciated:
- Fix typos or unclear wording
- Add examples or clarify existing ones
- Improve README, CHANGELOG, or code comments
- Add or improve rustdoc comments

## Development Workflow

### Creating a Branch

```bash
# Update your main branch
git checkout main
git pull upstream main

# Create a feature branch
git checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bug-fix
```

### Making Changes

1. Write your code following the [Coding Standards]#coding-standards
2. Add or update tests as needed
3. Update documentation (README, rustdoc, etc.)
4. Run the test suite
5. Run clippy and fix any warnings
6. Format your code

### Committing Changes

Write clear, descriptive commit messages:

```
Add JSON output format support

- Implement JSON serialization for CountResult
- Add --format json CLI option
- Add tests for JSON output
- Update documentation with JSON examples
```

Follow these guidelines:
- Use the imperative mood ("Add feature" not "Added feature")
- First line should be 50 characters or less
- Add a blank line after the first line
- Wrap subsequent lines at 72 characters
- Reference relevant issues (e.g., "Fixes #123")

## Coding Standards

### Rust Style Guide

- Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)
- Use `cargo fmt` to format code (enforced in CI)
- Use `cargo clippy` and address all warnings (enforced in CI)

### Code Organization

```
src/
├── main.rs          # Entry point (minimal)
├── lib.rs           # Library exports
├── cli.rs           # CLI argument parsing
├── world.rs         # Typst world implementation
├── counter.rs       # Counting logic
└── output/          # Output formatting
    ├── mod.rs
    ├── human.rs
    ├── json.rs
    └── csv.rs
```

### Best Practices

- **Keep functions small and focused**: Each function should do one thing well
- **Use descriptive names**: Variables, functions, and types should be self-documenting
- **Add comments for complex logic**: Explain *why*, not *what*
- **Use `Result` and `?` for error handling**: Avoid `unwrap()` in library code
- **Write rustdoc comments for public APIs**: Include examples where helpful
- **Prefer composition over inheritance**: Use traits and structs effectively

### Error Handling

```rust
// Good: Propagate errors with context
fn process_file(path: &Path) -> Result<CountResult> {
    let content = fs::read_to_string(path)
        .with_context(|| format!("Failed to read file: {}", path.display()))?;
    // ...
}

// Avoid: Unwrapping in library code
fn process_file(path: &Path) -> CountResult {
    let content = fs::read_to_string(path).unwrap(); // ❌
    // ...
}
```

## Testing

### Running Tests

```bash
# Run all tests
cargo test

# Run tests with output
cargo test -- --nocapture

# Run specific test
cargo test test_word_count

# Run tests with coverage (if installed)
cargo tarpaulin
```

### Writing Tests

- Add unit tests in the same file as the code being tested
- Add integration tests in `tests/` directory
- Test edge cases and error conditions
- Use descriptive test names

Example:

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_count_simple_document() {
        let input = "Hello world";
        let result = count_text(input);
        assert_eq!(result.words, 2);
        assert_eq!(result.characters, 11);
    }

    #[test]
    fn test_count_with_punctuation() {
        let input = "Hello, world!";
        let result = count_text(input);
        assert_eq!(result.words, 2);
        assert_eq!(result.characters, 13);
    }
}
```

### Test Coverage

We aim for high test coverage, especially for:
- Core counting logic
- CLI argument parsing
- Output formatting
- Error handling
- Edge cases (empty files, invalid input, etc.)

## Pull Request Process

### Before Submitting

Ensure your PR passes all checks:

```bash
# Format code
cargo fmt --all

# Run clippy
cargo clippy --all-targets --all-features -- -D warnings

# Run tests
cargo test

# Build release binary
cargo build --release
```

### Submitting a Pull Request

1. **Push your branch** to your fork:
   ```bash
   git push origin feature/your-feature-name
   ```

2. **Create a pull request** on GitHub

3. **Fill out the PR template** with:
   - Description of changes
   - Motivation and context
   - How to test the changes
   - Related issues (use "Fixes #123" to auto-close)
   - Screenshots (if UI changes)

4. **Wait for review**:
   - Address any feedback
   - Update your branch if needed
   - Be responsive to comments

### PR Guidelines

- Keep PRs focused on a single feature or fix
- Avoid mixing unrelated changes
- Rebase on main if your branch is outdated
- Update documentation as needed
- Add tests for new features
- Keep commits clean (consider squashing if many small commits)

### Review Process

- Maintainers will review your PR
- CI checks must pass (tests, clippy, formatting)
- At least one approval is required
- Feedback should be addressed or discussed
- Once approved, a maintainer will merge your PR

## Release Process

For maintainers only:

1. Update version in `Cargo.toml`
2. Update `CHANGELOG.md` with release date and notes
3. Commit: `git commit -am "Release v0.x.0"`
4. Tag: `git tag -a v0.x.0 -m "Release v0.x.0"`
5. Push: `git push && git push --tags`
6. Publish: `cargo publish`
7. Create GitHub release with changelog notes

## Questions?

If you have questions:
- Check existing issues and documentation
- Open a discussion issue
- Reach out to maintainers

Thank you for contributing!