Contributing to Mark
Thank you for your interest in contributing to Mark! This guide will help you get started with contributing to the project, whether you’re fixing bugs, adding features, or improving documentation.
Getting Started
Prerequisites
Before you begin, ensure you have the following installed:
- Rust (1.70 or later) - Install from rustup.rs
- Git - For version control
- A good text editor - VS Code, Vim, Emacs, etc.
Setting Up the Development Environment
-
Fork and Clone
# Fork the repository on GitHub, then clone your fork git clone https://github.com/YOUR_USERNAME/mark.git cd mark
-
Set up the upstream remote
git remote add upstream https://github.com/Pazl27/mark.git
-
Install dependencies and build
cargo build cargo test
-
Verify everything works
cargo run -- README.md
Development Workflow
Branch Management
We use a GitHub Flow approach:
-
Create a feature branch
git checkout -b feature/your-feature-name # or git checkout -b fix/bug-description
-
Keep your branch up to date
git fetch upstream git rebase upstream/main
-
Push and create PR
git push origin feature/your-feature-name # Then create a Pull Request on GitHub
Code Style and Standards
Rust Code Style
We follow standard Rust conventions:
- Use
cargo fmt
to format code - Use
cargo clippy
to catch common issues - Follow Rust naming conventions (snake_case, etc.)
- Write descriptive comments for complex logic
- Include unit tests for new functionality
Code Organization
The project is organized as follows:
src/
├── main.rs # CLI entry point
├── lib.rs # Library exports
├── cli/ # Command-line interface
├── config/ # Configuration handling
├── markdown_parser/ # Markdown parsing logic
│ ├── lexer/ # Tokenization
│ ├── parser/ # AST generation
│ └── renderer/ # Output generation
├── tui/ # Terminal UI components
├── theme/ # Theme system
├── search/ # Search functionality
└── error.rs # Error types and handling
Testing
- Write unit tests for all new functions
- Add integration tests for new features
- Include edge case tests
- Use descriptive test names
#![allow(unused)] fn main() { #[cfg(test)] mod tests { use super::*; #[test] fn test_lexer_handles_empty_input() { let mut lexer = Lexer::new(""); let tokens = lexer.tokenize().unwrap(); assert_eq!(tokens, vec![Token::Eof]); } #[test] fn test_parser_processes_headers() { // Test implementation } } }
Types of Contributions
Bug Reports
When reporting bugs, please include:
- Clear description of the issue
- Steps to reproduce the problem
- Expected vs actual behavior
- System information (OS, terminal, Rust version)
- Sample files that trigger the issue (if applicable)
Use this template:
## Bug Description
Brief description of what's wrong.
## Steps to Reproduce
1. Run `mark file.md`
2. Press key X
3. See error Y
## Expected Behavior
What should happen.
## Actual Behavior
What actually happens.
## Environment
- OS: Linux/macOS/Windows
- Terminal: Terminal app name and version
- Mark version: `mark --version`
- Rust version: `rustc --version`
## Additional Context
Any other relevant information.
Feature Requests
For new features, please:
- Search existing issues to avoid duplicates
- Describe the use case clearly
- Explain why this feature would be valuable
- Consider alternatives and their trade-offs
- Be open to discussion about implementation
Code Contributions
Small Changes
For small changes (typos, minor bug fixes):
- Create a branch
- Make your changes
- Test locally
- Submit a pull request
Large Changes
For significant changes:
- Open an issue first to discuss the approach
- Get feedback from maintainers
- Break down the work into smaller PRs if possible
- Follow the development workflow
Pull Request Guidelines
-
Write clear commit messages
feat: add syntax highlighting for code blocks - Implement highlighting using syntect crate - Add configuration options for themes - Include tests for various languages Closes #123
-
Keep PRs focused - one feature/fix per PR
-
Include tests for new functionality
-
Update documentation as needed
-
Ensure CI passes before requesting review
Development Tasks
Running Tests
# Run all tests
cargo test
# Run specific test module
cargo test lexer
# Run tests with output
cargo test -- --nocapture
# Run integration tests
cargo test --test integration
Code Quality Checks
# Format code
cargo fmt
# Check for issues
cargo clippy -- -D warnings
# Check for unused dependencies
cargo machete
Building Documentation
# Build API documentation
cargo doc --open
# Build user guide
cd docs
mdbook serve
Performance Testing
# Build optimized version
cargo build --release
# Profile with large files
cargo run --release -- large-file.md
# Benchmark lexer performance
cargo bench lexer
Architecture Overview
Core Components
-
Lexer (
src/markdown_parser/lexer/
)- Tokenizes markdown text
- Handles all markdown syntax elements
- Provides comprehensive error reporting
-
Parser (
src/markdown_parser/parser/
)- Converts tokens to Abstract Syntax Tree (AST)
- Handles markdown semantics
- Resolves references and links
-
Renderer (
src/markdown_parser/renderer/
)- Converts AST to terminal output
- Handles styling and theming
- Manages terminal-specific formatting
-
TUI (
src/tui/
)- Interactive terminal interface
- Navigation and input handling
- File browser and search
-
Configuration (
src/config/
)- TOML configuration parsing
- Theme management
- User preferences
Design Principles
- Performance: Fast startup and rendering
- Reliability: Handle edge cases gracefully
- Usability: Intuitive interface and helpful errors
- Extensibility: Plugin system for custom features
- Portability: Cross-platform compatibility
Common Development Tasks
Adding a New Token Type
- Add token variant to
src/markdown_parser/lexer/tokens.rs
- Update lexer logic in
src/markdown_parser/lexer/lexer.rs
- Add parser support in
src/markdown_parser/parser/
- Update renderer in
src/markdown_parser/renderer/
- Add comprehensive tests
Adding a Configuration Option
- Update config struct in
src/config/mod.rs
- Add default value and validation
- Update TOML parsing logic
- Add CLI flag if needed
- Update documentation
Adding a New Theme
- Create theme file in
src/theme/
- Register theme in theme system
- Add color definitions
- Test with various content types
- Update documentation
Release Process
Version Numbering
We follow Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
Release Checklist
- Update version in
Cargo.toml
- Update
CHANGELOG.md
- Run full test suite
- Build documentation
- Create git tag
- Publish to crates.io (maintainers only)
Getting Help
Community Channels
- GitHub Issues: Bug reports and feature requests
- GitHub Discussions: General questions and ideas
- Discord (if available): Real-time chat
Documentation
- User Guide: How to use Mark
- API Documentation: Code-level documentation
- Architecture Guide: High-level design decisions
Mentorship
New contributors are always welcome! If you’re new to:
- Rust: Check out the Rust Book
- Terminal apps: Look at similar projects like
bat
,fd
,ripgrep
- Open source: Read the Open Source Guide
Code of Conduct
We are committed to providing a welcoming and inclusive environment. Please:
- Be respectful in all interactions
- Be constructive in feedback and criticism
- Be patient with new contributors
- Follow our Code of Conduct
Recognition
Contributors are recognized in several ways:
- Changelog: Major contributions mentioned in releases
- README: Contributors section
- All-Contributors: Recognizes all types of contributions
Thank You!
Every contribution, no matter how small, helps make Mark better. Whether you’re:
- Reporting bugs
- Fixing typos
- Adding features
- Improving documentation
- Helping other users
Your efforts are appreciated and help build a better tool for everyone.