Mark - Markdown Viewer
Welcome to Mark, a fast and elegant terminal-based markdown viewer and renderer written in Rust.
What is Mark?
Mark is a command-line utility that brings beautiful markdown rendering directly to your terminal. Whether you’re reading documentation, reviewing code comments, or browsing through markdown files, Mark provides a smooth and feature-rich experience without leaving your terminal environment.
Key Features
- Fast Performance - Built with Rust for lightning-fast rendering
- Beautiful TUI - Powered by Ratatui for a smooth terminal interface
- Syntax Highlighting - Full code block syntax highlighting
- Multiple Themes - Choose from various color schemes
- File Navigation - Easy browsing and searching of markdown files
- Configurable - Extensive customization via TOML configuration
- Smart Search - Find content across multiple files
- Cross-platform - Works on Linux, macOS, and Windows
Quick Start
# View a single markdown file
mark README.md
# Browse markdown files in a directory
mark ./docs/
# Use with custom configuration
mark --config ~/.config/mark/config.toml README.md
Architecture Overview
Mark is built with a modular architecture:
- Lexer - Tokenizes markdown syntax with comprehensive error handling
- Parser - Converts tokens into a structured document tree
- Renderer - Transforms the document into beautiful terminal output
- TUI - Provides interactive navigation and user interface
- Configuration - Handles themes, settings, and user preferences
Getting Help
- Read the User Guide for detailed instructions
- Check out Usage Examples for common workflows
- See the Developer Guide to contribute
- Report issues on GitHub
Ready to get started? Head over to the Installation guide!
Installation
This guide will walk you through installing Mark on your system.
Prerequisites
Before installing Mark, ensure you have the following:
- Rust (1.70 or later) - Install from rustup.rs
- Git - For cloning the repository
- A modern terminal with UTF-8 support
Installation Methods
From Source (Recommended)
The easiest way to install Mark is directly from the source code:
# Clone the repository
git clone https://github.com/Pazl27/mark.git
cd mark
# Build and install
cargo install --path .
Using Cargo Install (Future)
Once published to crates.io, you’ll be able to install with:
cargo install mark
Pre-built Binaries (Future)
Pre-built binaries will be available for download from the GitHub releases page for:
- Linux (x86_64, ARM64)
Verify Installation
After installation, verify that Mark is working correctly:
# Check version
mark --version
# View help
mark --help
# Test with a sample file
echo "# Hello World\n\nThis is a test file." > test.md
mark test.md
System Requirements
- Memory: Minimum 256MB RAM
- Terminal: Any modern terminal emulator
- Colors: 256-color support recommended for best experience
Troubleshooting
Common Issues
Rust not found
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
Compilation errors
# Update Rust to latest version
rustup update
Permission denied (Unix systems)
# Install to user directory instead
cargo install --path . --root ~/.local
export PATH="$HOME/.local/bin:$PATH"
Getting Help
If you encounter issues:
- Search existing GitHub issues
- Create a new issue with your system details
Next Steps
Once installed, head over to Getting Started to learn how to use Mark!
Getting Started
Welcome to Mark! This guide will help you get up and running with the markdown viewer in just a few minutes.
First Steps
After installing Mark, let’s start with the basics.
Viewing a Single File
The simplest way to use Mark is to view a single markdown file:
mark README.md
This will open the file in Mark’s terminal interface where you can:
- Scroll through the content with arrow keys
- Navigate sections with Page Up/Page Down
- Press
q
to quit
Browsing a Directory
Mark can also browse through multiple markdown files in a directory:
mark ./docs/
This opens a file browser where you can:
- Use arrow keys to navigate files
- Press Enter to open a file
- Press Escape to go back to the file list
Basic Navigation
Keyboard Shortcuts
Key | Action |
---|---|
↑k/↓j | Scroll up/down |
gg/G | Go to beginning/end |
q or Ctrl+C | Quit |
? | Show help |
/ | Search |
Configuration
Mark uses a TOML configuration file for customization. Create a config file at:
- Linux/macOS:
~/.config/mark/config.toml
- Windows:
%APPDATA%\mark\config.toml
Basic Configuration
// TODO
Reading Documentation
# Browse project documentation
mark ./project-docs/
# Read a specific guide
mark ./project-docs/user-guide.md
2. Configuration Profiles
You can use different configurations for different contexts:
# Use work configuration
mark --config ~/.config/mark/config1.toml document.md
# Use presentation theme
mark --config ~/.config/mark/config2.toml slides.md
Common Use Cases
Documentation Reading
Perfect for browsing project documentation, API references, and technical guides without leaving the terminal.
Code Review
Quickly review README files, changelogs, and documentation changes during code reviews.
Writing and Editing
Use Mark alongside your favorite editor to preview markdown as you write.
Presentations
Use Mark’s clean rendering for terminal-based presentations and demos.
What’s Next?
- Learn about Configuration options
- Explore Usage Examples for advanced workflows
- Check out the Developer Guide to contribute
Getting Help
If you need help:
- Press
?
in Mark to see keyboard shortcuts - Visit the GitHub repository for issues and discussions
Configuration
Mark is highly configurable through TOML configuration files. This guide covers all available configuration options and how to customize Mark to your preferences.
Usage Examples
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.
Architecture Overview
This document provides a comprehensive overview of Mark’s architecture, design decisions, and implementation details. Understanding this architecture will help you contribute effectively to the project.
High-Level Architecture
Mark follows a modular, pipeline-based architecture that processes markdown content through several distinct stages:
Input → Lexer → Parser → AST → Renderer → TUI → Output
Core Pipeline
- Input Processing: Raw markdown text or file paths
- Lexical Analysis: Tokenization of markdown syntax
- Parsing: Construction of Abstract Syntax Tree (AST)
- Rendering: Conversion to terminal-friendly format
- Display: Interactive terminal user interface
- Output: Rendered content with navigation
Module Structure
Project Layout
src/
├── main.rs # CLI entry point and argument parsing
├── lib.rs # Public API and module exports
├── cli/ # Command-line interface logic
│ ├── mod.rs # CLI module definition
│ ├── args.rs # Argument parsing and validation
│ └── commands.rs # Command implementations
├── config/ # Configuration system
│ ├── mod.rs # Configuration management
│ ├── loader.rs # Config file loading and parsing
│ ├── theme.rs # Theme configuration
│ └── validation.rs # Config validation logic
├── markdown_parser/ # Core markdown processing
│ ├── mod.rs # Parser module exports
│ ├── lexer/ # Lexical analysis
│ │ ├── mod.rs # Lexer module definition
│ │ ├── lexer.rs # Main lexer implementation
│ │ └── tokens.rs # Token definitions
│ ├── parser/ # Syntax analysis (future)
│ │ ├── mod.rs # Parser implementation
│ │ ├── ast.rs # AST node definitions
│ │ └── builder.rs # AST construction logic
│ └── renderer/ # Output generation (future)
│ ├── mod.rs # Renderer implementations
│ ├── terminal.rs # Terminal-specific rendering
│ └── html.rs # HTML export functionality
├── tui/ # Terminal user interface (future)
│ ├── mod.rs # TUI module definition
│ ├── app.rs # Main application state
│ ├── events.rs # Event handling
│ └── widgets/ # Custom UI widgets
├── theme/ # Theme system (future)
│ ├── mod.rs # Theme management
│ ├── colors.rs # Color definitions
│ └── builtin.rs # Built-in themes
├── search/ # Search functionality (future)
│ ├── mod.rs # Search implementation
│ └── index.rs # Search indexing
└── error.rs # Error types and handling
API Reference
MIT License
Copyright (c) 2025 Pazl
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.