Metadata-Version: 2.4
Name: accessible-math-reader
Version: 0.4.1
Summary: Screen-reader-first math accessibility toolkit for converting LaTeX/MathML to speech and Braille. Developed under FCRIT Vashi.
Project-URL: Homepage, https://github.com/AndyFerns/Accessible-Math-Reader
Project-URL: Documentation, https://accessible-math-reader.readthedocs.io/en/latest/
Project-URL: Repository, https://github.com/AndyFerns/Accessible-Math-Reader
Project-URL: Issues, https://github.com/AndyFerns/Accessible-Math-Reader/issues
Project-URL: College, https://fcrit.ac.in/
Author-email: Andrew Fernandes <write2andrew.fernandes@gmail.com>, Aaron Anthony <aaronantonytheofficial@gmail.com>, Chris Anil <chrisanil777@gmail.com>
License: Copyright (c) 2026 Andrew Fernandes
        
        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.
License-File: LICENSE
Keywords: accessibility,braille,latex,math,mathml,screen-reader
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Education
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Text Processing
Requires-Python: >=3.9
Requires-Dist: gtts>=2.5.0
Requires-Dist: lxml>=4.9.0
Provides-Extra: all
Requires-Dist: flask>=3.0.0; extra == 'all'
Requires-Dist: gunicorn>=21.2.0; (sys_platform != 'win32') and extra == 'all'
Requires-Dist: ipython>=8.0.0; extra == 'all'
Requires-Dist: prometheus-client>=0.19.0; extra == 'all'
Requires-Dist: pyttsx3>=2.90; extra == 'all'
Provides-Extra: api
Requires-Dist: flask>=3.0.0; extra == 'api'
Requires-Dist: gunicorn>=21.2.0; (sys_platform != 'win32') and extra == 'api'
Provides-Extra: dev
Requires-Dist: axe-playwright-python>=0.1.0; extra == 'dev'
Requires-Dist: playwright>=1.40.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: grpc
Requires-Dist: grpcio-tools>=1.60.0; extra == 'grpc'
Requires-Dist: grpcio>=1.60.0; extra == 'grpc'
Requires-Dist: protobuf>=4.25.0; extra == 'grpc'
Provides-Extra: jupyter
Requires-Dist: ipython>=8.0.0; extra == 'jupyter'
Provides-Extra: metrics
Requires-Dist: prometheus-client>=0.19.0; extra == 'metrics'
Provides-Extra: offline-tts
Requires-Dist: pyttsx3>=2.90; extra == 'offline-tts'
Provides-Extra: tracing
Requires-Dist: opentelemetry-api>=1.22.0; extra == 'tracing'
Requires-Dist: opentelemetry-sdk>=1.22.0; extra == 'tracing'
Provides-Extra: web
Requires-Dist: flask>=3.0.0; extra == 'web'
Description-Content-Type: text/markdown

<p align="center">
  <h1 align="center">♿ Accessible Math Reader</h1>
  <p align="center">
    <strong>A screen-reader-first mathematical accessibility toolkit for converting LaTeX, MathML, and plaintext/Unicode math into speech, Braille, and navigable ARIA structures.</strong>
  </p>
</p>

<p align="center">
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License"></a>
  <a href="https://python.org"><img src="https://img.shields.io/badge/Python-3.9+-green.svg" alt="Python 3.9+"></a>
  <a href="#"><img src="https://img.shields.io/badge/Status-Alpha-orange.svg" alt="Alpha"></a>
  <a href="https://www.w3.org/WAI/standards-guidelines/wcag/"><img src="https://img.shields.io/badge/WCAG-2.2_AA-purple.svg" alt="WCAG 2.2 AA"></a>
</p>

<p align="center">
  <a href="#-quick-start">Quick Start</a> •
  <a href="#-features">Features</a> •
  <a href="#-installation">Installation</a> •
  <a href="#-usage">Usage</a> •
  <a href="docs/api.md">API Reference</a> •
  <a href="#-contributing">Contributing</a>
</p>

---

## 📖 Overview

**Accessible Math Reader (AMR)** is a Python package and web application that makes mathematical notation accessible to visually impaired users. It parses LaTeX, MathML, and plaintext/Unicode math expressions and converts them into:

- **Natural language speech** with configurable verbosity (verbose, concise, superbrief)
- **Braille notation** in both Nemeth (US standard) and UEB (international standard)
- **Audio files** via Google Text-to-Speech (gTTS)
- **ARIA-annotated HTML** for keyboard-navigable, screen-reader-friendly exploration

AMR can be used as a **Python library**, a **CLI tool**, or through a **Flask-based web interface**.

> 🎓 Developed at FCRIT Vashi as a project in academic research in accessibility and inclusive technology.

---

## ✨ Features

| Category | Highlights |
|---|---|
| **📖 Multi-Format Input** | Parse LaTeX, MathML, and plaintext/Unicode math expressions with auto-detection |
| **🔊 Speech Output** | Natural language descriptions with 3 verbosity levels and SSML support |
| **⠿ Braille Support** | Full Nemeth Braille Code and Unified English Braille (UEB) converters |
| **♿ ARIA Navigation** | Keyboard-accessible, step-by-step expression exploration with 3 navigation modes |
| **📋 Multi-Format Clipboard** | Copy formulas as LaTeX, accessible text, or Braille from the web UI |
| **🎨 Accessible Web UI** | Dark/light themes, high-contrast mode, zoom controls, screen-reader optimized |
| **🔌 Plugin System** | Extensible architecture for custom speech rules, Braille notations, and input formats |
| **⌨️ CLI Tool** | Full-featured command-line interface with interactive and batch modes |

---

## 🏗️ Architecture

```plaintext
┌─────────────────────────────────────────────────────────────────────┐
│                        Accessible Math Reader                       │
├──────────┬──────────┬───────────────────────────────┬───────────────┤
│  CLI     │  Web UI  │      Python API (MathReader)  │   Plugins     │
│  (amr)   │  (Flask) │                               │  (extensible) │
├──────────┴──────────┴───────────────────────────────┴───────────────┤
│                        Core Pipeline                                │
│  ┌──────────┐   ┌──────────────┐   ┌────────────────────────────┐   │
│  │  Parser  │──▸│ Semantic AST │──▸│        Renderers           │   │
│  │  LaTeX   │   │ (SemanticNode│   │  ┌─────────┬────────────┐  │   │
│  │  MathML  │   │  NodeType)   │   │  │ Speech  │  Braille   │  │   │
│  │ Plaintext│   |              |   |  |         |            |  |   |
│  └──────────┘   └──────┬───────┘   │  │ Engine  │ Nemeth/UEB │  │   │
│                        │           │  └─────────┴────────────┘  │   │
│                        ▼           │  ┌─────────┬────────────┐  │   │
│                  ┌───────────┐     │  │  ARIA   │  Simple    │  │   │
│                  │ Navigator │     │  │Renderer │  Text      │  │   │
│                  │ (keyboard │     │  └─────────┴────────────┘  │   │
│                  │  explore) │     └────────────────────────────┘   │
│                  └───────────┘                                      │
├─────────────────────────────────────────────────────────────────────┤
│                        Configuration                                │
│        Config  ·  SpeechConfig  ·  BrailleConfig  ·  A11yConfig     │
└─────────────────────────────────────────────────────────────────────┘
```

### Project Structure

```
accessible-math-reader/
├── accessible_math_reader/       # 📦 Installable Python package
│   ├── __init__.py               #    Public API exports
│   ├── reader.py                 #    MathReader — high-level unified interface
│   ├── cli.py                    #    CLI entry point (`amr` command)
│   ├── config.py                 #    Configuration management (env, file, API)
│   ├── core/                     #    Core parsing & rendering engine
│   │   ├── parser.py             #      LaTeX / MathML / Plaintext → Semantic AST
│   │   ├── semantic.py           #      SemanticNode, NodeType, MathNavigator
│   │   ├── renderer.py           #      Base rendering infrastructure
│   │   ├── aria_navigator.py     #      ARIA-enhanced keyboard navigation
│   │   ├── aria_renderer.py      #      Accessible HTML generation
│   │   └── accessibility_contract.py  #  Accessibility validation contracts
│   ├── speech/                   #    Speech output subsystem
│   │   ├── engine.py             #      TTS engine abstraction (gTTS backend)
│   │   └── rules.py              #      Verbosity-based speech rules
│   ├── braille/                  #    Braille conversion subsystem
│   │   ├── nemeth.py             #      Nemeth Braille Code converter
│   │   └── ueb.py                #      Unified English Braille converter
│   └── plugins/                  #    Plugin system
│       └── base.py               #      Abstract plugin base classes
├── app.py                        # 🌐 Flask web application entry point
├── src/                          #    Legacy web-app helper modules
│   ├── latex_parser.py           #      Regex-based LaTeX parser (for Flask UI)
│   ├── braille_converter.py      #      Simple character-level Braille mapper
│   └── speech_converter.py       #      gTTS wrapper for web UI
├── templates/
│   └── index.html                # 🖥️  Web UI template (dark/light, accessible)
├── static/
│   ├── css/style.css             #    Web UI styles
│   └── js/
│       ├── app.js                #    Frontend logic & keyboard shortcuts
│       └── clipboard.js          #    Multi-format clipboard support
├── docs/                         # 📚 Documentation
│   ├── api.md                    #    Full Python API reference
│   ├── input-formats.md          #    Supported LaTeX & MathML syntax
│   ├── accessibility.md          #    Screen reader, Braille & ARIA guide
│   ├── configuration.md          #    Configuration reference
│   └── examples.md               #    Code samples & use cases
├── output/                       #    Sample Braille output files (.brf)
├── pyproject.toml                #    Package metadata & build config
├── requirements.txt              #    Web-app-specific dependencies
└── LICENSE                       #    MIT License
```

---

## 🚀 Installation

### As a Python Package (Recommended)

Install directly from the repository:

```bash
# Clone the repository
git clone https://github.com/AndyFerns/Accessible-Math-Reader.git
cd Accessible-Math-Reader

# Create and activate a virtual environment
python -m venv venv
# Windows
venv\Scripts\activate
# Linux / macOS
source venv/bin/activate

# Install the package in editable mode (with all extras)
pip install -e ".[dev,web]"
```

This installs AMR as a package and registers the `amr` CLI command.

### Minimal Install (Library Only)

If you only need the Python API (no web UI, no dev tools):

```bash
pip install -e .
```

Core dependencies are just `gtts` and `lxml`.

### From PyPI *(coming soon)*

```bash
pip install accessible-math-reader
```

---

## 📋 Usage

AMR provides **three interfaces**: a Python API, a CLI tool, and a web UI.

### 1. Python API

```python
from accessible_math_reader import MathReader

reader = MathReader()

# ── Speech ──────────────────────────────────────────
speech = reader.to_speech(r"\frac{a}{b}")
print(speech)
# → "start fraction a over b end fraction"

# ── Braille (Nemeth) ────────────────────────────────
braille = reader.to_braille(r"\frac{a}{b}", notation="nemeth")
print(braille)
# → "⠹⠁⠌⠃⠼"

# ── Braille (UEB) ──────────────────────────────────
ueb = reader.to_braille(r"\frac{a}{b}", notation="ueb")

# ── Audio file ──────────────────────────────────────
reader.to_audio(r"\frac{a}{b}", "output.mp3")

# ── SSML markup ─────────────────────────────────────
ssml = reader.to_ssml(r"\sqrt{x}")

# ── Semantic tree inspection ────────────────────────
structure = reader.get_structure(r"\frac{a+b}{c}")

# ── Plaintext / Unicode math ────────────────────────
speech = reader.to_speech("x² + y² = z²")
speech = reader.to_speech("(a+b)/(c-d)")
speech = reader.to_speech("sqrt(x) + π")
```

#### Changing Verbosity

```python
from accessible_math_reader import MathReader, VerbosityLevel

reader = MathReader()

reader.set_verbosity(VerbosityLevel.VERBOSE)
reader.to_speech(r"\frac{a}{b}")   # "start fraction a over b end fraction"

reader.set_verbosity(VerbosityLevel.CONCISE)
reader.to_speech(r"\frac{a}{b}")   # "a over b"

reader.set_verbosity(VerbosityLevel.SUPERBRIEF)
reader.to_speech(r"\frac{a}{b}")   # "fraction a b"
```

#### Custom Configuration

```python
from accessible_math_reader import MathReader, Config
from accessible_math_reader.config import SpeechConfig, BrailleConfig, SpeechStyle, BrailleNotation

config = Config(
    speech=SpeechConfig(style=SpeechStyle.CONCISE, language="en", rate=0.9),
    braille=BrailleConfig(notation=BrailleNotation.UEB),
)

reader = MathReader(config)
```

#### Step-by-Step Navigation

```python
nav = reader.get_navigator(r"\frac{a+b}{c}")
nav.enter()       # Drill into the fraction
nav.next()        # Move to the next sibling
nav.exit()        # Go back up to the parent
path = nav.get_path()  # Breadcrumb trail from root
```

---

### 2. Command-Line Interface (`amr`)

After installing the package, the `amr` command is available system-wide.

```bash
# Speech output (default)
amr "\frac{a^2 + b^2}{c}"

# Plaintext / Unicode math
amr "x² + y² = z²"
amr "(a+b)/(c-d)"
amr "sqrt(x) + π"

# Braille output (Nemeth)
amr --braille "\frac{a}{b}"

# Braille output (UEB)
amr --braille --notation ueb "\sqrt{x}"

# Generate audio file
amr --audio output.mp3 "\frac{1}{2}"

# SSML output
amr --ssml "\frac{a}{b}"

# JSON output (speech + braille + structure)
amr --json "\frac{a}{b}"

# Show expression tree structure
amr --structure "\frac{a+b}{c}"

# Set verbosity
amr --verbosity concise "x^2 + y^2 = z^2"

# Read from file (one expression per line)
amr --input equations.txt

# Write output to file
amr --output results.txt "\frac{a}{b}"

# Interactive REPL mode
amr --interactive
```

#### Interactive Mode Commands

| Command | Action |
|---|---|
| `:quit` / `:exit` | Exit interactive mode |
| `:verbosity <level>` | Set verbosity (verbose, concise, superbrief) |
| `:braille` | Switch to Braille output |
| `:speech` | Switch to speech output |
| `:help` | Show all commands |

---

### 3. Web Interface

The web UI provides a visual, accessible interface built with Flask:

```bash
# Install web dependencies
pip install -e ".[web]"

# Start the development server
python app.py

# Open http://localhost:5000
```

**Web UI Features:**
- LaTeX / MathML / plaintext/Unicode input with live conversion
- Tabbed output: Formula preview, Speech text, Braille, Accessible ARIA view
- Multi-format clipboard (copy as LaTeX, plain text, or Braille)
- Dark / Light / High-Contrast themes
- Full keyboard navigation (`Ctrl+Enter` to convert, `Alt+1–4` to switch tabs)
- Screen-reader optimized with ARIA live regions

---

## ⚙️ Configuration

AMR supports three configuration methods (highest priority first):

### 1. Environment Variables

```bash
# Linux / macOS
export AMR_SPEECH_STYLE=concise        # verbose | concise | superbrief
export AMR_BRAILLE_NOTATION=nemeth     # nemeth | ueb
export AMR_SPEECH_LANGUAGE=en          # Language code
export AMR_PLUGIN_DIRS=/path/to/plugins

# Windows PowerShell
$env:AMR_SPEECH_STYLE = "concise"
$env:AMR_BRAILLE_NOTATION = "ueb"
```

### 2. JSON Config File

```json
{
  "speech": {
    "style": "verbose",
    "language": "en",
    "rate": 1.0,
    "announce_structure": true
  },
  "braille": {
    "notation": "nemeth",
    "include_indicators": true
  },
  "accessibility": {
    "step_by_step": true,
    "announce_errors": true,
    "highlight_current": true
  }
}
```

```python
config = Config.from_file("amr-config.json")
reader = MathReader(config)
```

### 3. Python API

```python
config = Config()
config.speech.style = SpeechStyle.CONCISE
config.save("my-config.json")
```

> 📖 Full configuration reference: [docs/configuration.md](docs/configuration.md)

---

## 🔌 Plugin System

AMR's plugin architecture supports four extension points:

| Plugin Type | Base Class | Purpose |
|---|---|---|
| **Speech Rules** | `SpeechRulesPlugin` | Custom verbalization rules for math constructs |
| **Braille Notation** | `BrailleNotationPlugin` | Additional Braille systems (French, German, etc.) |
| **Input Format** | `InputFormatPlugin` | New input parsers (AsciiMath, MathJSON, etc.) |
| **Localization** | `BasePlugin` | Language/locale-specific adaptations |

```python
from accessible_math_reader.plugins.base import SpeechRulesPlugin, PluginInfo, PluginType

class MyCustomRules(SpeechRulesPlugin):
    @property
    def info(self):
        return PluginInfo(
            name="my-rules",
            version="1.0.0",
            description="Custom speech rules",
            author="Your Name",
            plugin_type=PluginType.SPEECH_RULES,
        )

    def get_speech_rules(self):
        return {"FRACTION": lambda node: "custom fraction rendering"}
```

---

## 📚 Documentation

| Document | Description |
|---|---|
| [API Reference](docs/api.md) | Full Python API with code examples |
| [Input Formats](docs/input-formats.md) | Supported LaTeX commands and MathML elements |
| [Accessibility Guide](docs/accessibility.md) | Screen reader, Braille display, and ARIA features |
| [Configuration](docs/configuration.md) | All speech, Braille, and accessibility settings |
| [Examples](docs/examples.md) | Common use cases, batch processing, and web integration |

### Generating Documentation Locally

This project uses [MkDocs](https://www.mkdocs.org/) with the Material theme for documentation hosting:

```bash
# Install documentation dependencies
pip install mkdocs mkdocs-material mkdocstrings[python]

# Serve docs locally (live reload)
mkdocs serve

# Build static site
mkdocs build
```

> See [mkdocs.yml](mkdocs.yml) for the full configuration.

---

## 🎯 Accessibility Compliance

| Standard | Status |
|---|---|
| **WCAG 2.2 AA** | ✅ Full compliance for web interface |
| **WAI-ARIA 1.2** | ✅ Proper roles, labels, live regions, roving tabindex |
| **Screen Readers** | ✅ Tested with NVDA, JAWS, VoiceOver, Narrator |
| **Keyboard Navigation** | ✅ Full keyboard access, visible focus indicators |
| **Braille Displays** | ✅ Unicode Braille output compatible with refreshable displays |

---

## 🧑‍💻 Development

### Prerequisites

- Python 3.9+
- pip

### Setup

```bash
git clone https://github.com/AndyFerns/Accessible-Math-Reader.git
cd Accessible-Math-Reader

python -m venv venv
venv\Scripts\activate          # Windows
# source venv/bin/activate     # Linux / macOS

pip install -e ".[dev,web]"
```

### Running Tests

```bash
# Run full test suite with coverage
pytest tests/ -v --cov=accessible_math_reader --cov-report=term-missing

# Run a specific test file
pytest tests/test_parser.py -v
```

### Linting

```bash
# Run ruff linter
ruff check accessible_math_reader/

# Auto-fix lint issues
ruff check accessible_math_reader/ --fix
```

### Running the Web Server

```bash
python app.py
# Open http://localhost:5000
```

---

## 🤝 Contributing

We welcome contributions! Here's how to get started:

1. **Fork** the repository
2. **Create a feature branch**: `git checkout -b feature/your-feature`
3. **Install dev dependencies**: `pip install -e ".[dev]"`
4. **Make your changes** and add tests
5. **Run the linter**: `ruff check accessible_math_reader/`
6. **Run the tests**: `pytest tests/ -v`
7. **Commit** with a descriptive message
8. **Push** to your fork and open a **Pull Request**

### Areas Where Help Is Needed

- 🌍 **Localization**: Speech rules for other languages
- ⠿ **Braille**: Additional Braille notation systems (French, German, etc.)
- 🧪 **Testing**: More unit tests, especially for edge-case math expressions
- ♿ **User Testing**: Feedback from blind and low-vision users
- 📝 **Documentation**: Tutorials, guides, and examples

---

## 📦 Releasing as a Package

### Building the Distribution

```bash
# Install build tool
pip install build

# Build source distribution and wheel
python -m build

# Output will be in dist/
#   dist/accessible_math_reader-0.1.0.tar.gz
#   dist/accessible_math_reader-0.1.0-py3-none-any.whl
```

### Publishing to PyPI

```bash
# Install twine
pip install twine

# Upload to TestPyPI (for testing)
twine upload --repository testpypi dist/*

# Upload to PyPI (production)
twine upload dist/*
```

### Installing from the Built Package

```bash
# From the wheel file
pip install dist/accessible_math_reader-0.1.0-py3-none-any.whl

# From TestPyPI
pip install --index-url https://test.pypi.org/simple/ accessible-math-reader

# From PyPI (once published)
pip install accessible-math-reader
```

---

## 📄 License

This project is licensed under the **MIT License** — see the [LICENSE](LICENSE) file for details.

---

## 🙏 Acknowledgments

- [gTTS](https://gtts.readthedocs.io/) — Google Text-to-Speech engine
- [lxml](https://lxml.de/) — XML/MathML parsing
- [Flask](https://flask.palletsprojects.com/) — Web framework
- [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/) — Accessibility guidelines
- [Nemeth Braille Code](https://en.wikipedia.org/wiki/Nemeth_Braille) — Mathematical Braille standard
- [UEB](https://www.uebonline.org/) — Unified English Braille
- [FCRIT](https://fcrit.ac.in/) - Fr. Conceicao Rodrigues Institute of Technology

---

<p align="center">
  Built with ♿ accessibility as a first-class priority.
</p>
