Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

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

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:

  1. Search existing GitHub issues
  2. 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

KeyAction
↑k/↓jScroll up/down
gg/GGo to beginning/end
q or Ctrl+CQuit
?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?

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

  1. Fork and Clone

    # Fork the repository on GitHub, then clone your fork
    git clone https://github.com/YOUR_USERNAME/mark.git
    cd mark
    
  2. Set up the upstream remote

    git remote add upstream https://github.com/Pazl27/mark.git
    
  3. Install dependencies and build

    cargo build
    cargo test
    
  4. Verify everything works

    cargo run -- README.md
    

Development Workflow

Branch Management

We use a GitHub Flow approach:

  1. Create a feature branch

    git checkout -b feature/your-feature-name
    # or
    git checkout -b fix/bug-description
    
  2. Keep your branch up to date

    git fetch upstream
    git rebase upstream/main
    
  3. 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):

  1. Create a branch
  2. Make your changes
  3. Test locally
  4. Submit a pull request

Large Changes

For significant changes:

  1. Open an issue first to discuss the approach
  2. Get feedback from maintainers
  3. Break down the work into smaller PRs if possible
  4. 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

  1. Lexer (src/markdown_parser/lexer/)

    • Tokenizes markdown text
    • Handles all markdown syntax elements
    • Provides comprehensive error reporting
  2. Parser (src/markdown_parser/parser/)

    • Converts tokens to Abstract Syntax Tree (AST)
    • Handles markdown semantics
    • Resolves references and links
  3. Renderer (src/markdown_parser/renderer/)

    • Converts AST to terminal output
    • Handles styling and theming
    • Manages terminal-specific formatting
  4. TUI (src/tui/)

    • Interactive terminal interface
    • Navigation and input handling
    • File browser and search
  5. 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

  1. Add token variant to src/markdown_parser/lexer/tokens.rs
  2. Update lexer logic in src/markdown_parser/lexer/lexer.rs
  3. Add parser support in src/markdown_parser/parser/
  4. Update renderer in src/markdown_parser/renderer/
  5. Add comprehensive tests

Adding a Configuration Option

  1. Update config struct in src/config/mod.rs
  2. Add default value and validation
  3. Update TOML parsing logic
  4. Add CLI flag if needed
  5. Update documentation

Adding a New Theme

  1. Create theme file in src/theme/
  2. Register theme in theme system
  3. Add color definitions
  4. Test with various content types
  5. Update documentation

Release Process

Version Numbering

We follow Semantic Versioning:

  • MAJOR: Breaking changes
  • MINOR: New features (backward compatible)
  • PATCH: Bug fixes

Release Checklist

  1. Update version in Cargo.toml
  2. Update CHANGELOG.md
  3. Run full test suite
  4. Build documentation
  5. Create git tag
  6. 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

  1. Input Processing: Raw markdown text or file paths
  2. Lexical Analysis: Tokenization of markdown syntax
  3. Parsing: Construction of Abstract Syntax Tree (AST)
  4. Rendering: Conversion to terminal-friendly format
  5. Display: Interactive terminal user interface
  6. 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.