Metadata-Version: 2.4
Name: anki-yaml-tool
Version: 0.4.0
Summary: A generic tool for building and pushing Anki decks from YAML
License: GPL-3.0-only
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: genanki
Requires-Dist: requests
Requires-Dist: pyyaml
Requires-Dist: click
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: ruff>=0.1.9; extra == "dev"
Requires-Dist: mypy>=1.7.0; extra == "dev"
Requires-Dist: types-requests; extra == "dev"
Requires-Dist: types-PyYAML; extra == "dev"
Requires-Dist: pre-commit>=3.5.0; extra == "dev"
Requires-Dist: pyinstaller>=6.0.0; extra == "dev"
Dynamic: license-file

# Anki Python Deck Tool

[![Python Version](https://img.shields.io/badge/python-3.10%2B-blue)]()
[![License: GPL-3.0](https://img.shields.io/badge/License-GPL%203.0-blue.svg)](https://opensource.org/licenses/GPL-3.0)
[![CI Status](https://github.com/mrMaxwellTheCat/Anki-python-deck-tool/workflows/CI/badge.svg)](https://github.com/mrMaxwellTheCat/Anki-python-deck-tool/actions)
[![codecov](https://codecov.io/gh/mrMaxwellTheCat/Anki-python-deck-tool/branch/main/graph/badge.svg)](https://codecov.io/gh/mrMaxwellTheCat/Anki-python-deck-tool)

A professional, modular command-line tool to generate Anki decks (`.apkg`) from human-readable YAML source files and push them directly to Anki via AnkiConnect.

## Table of Contents

- [Features](#features)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage](#usage)
  - [Building a Deck](#1-build-a-deck-build)
  - [Pushing to Anki](#2-push-to-anki-push)
- [File Formats](#file-formats)
  - [Configuration File (Model)](#configuration-file-model)
  - [Data File (Notes)](#data-file-notes)
- [Project Structure](#project-structure)
- [Development](#development)
- [Future Plans](#future-plans)
- [Contributing](#contributing)
- [License](#license)

## Features

- **YAML-based Workflow**: Define your card models (CSS, templates) and data in clean YAML files.
- **Automated Sync**: Push generated decks directly to a running Anki instance via AnkiConnect.
- **Stable IDs**: Generates deterministic deck and model IDs based on names to preserve study progress across updates.
- **Tag Support**: Automatically handles tags and ID-based tagging for organization.
- **Flexible Architecture**: Modular design supporting multiple note types and custom configurations.
- **Type-Safe**: Modern Python type hints throughout the codebase.
- **Well-Tested**: Comprehensive test suite with pytest (96.77% coverage).
- **Standalone Executables**: Build single-file executables for Windows, macOS, and Linux.
- **CI/CD Pipeline**: Automated testing, security scanning, and releases.

## Prerequisites

Before using this tool, ensure you have the following:

1.  **Python 3.10+** installed.
2.  **Anki Desktop** installed and running (only required for the `push` command).
3.  **AnkiConnect** add-on installed in Anki (only required for the `push` command).
    - Open Anki → Tools → Add-ons → Get Add-ons...
    - Code: `2055492159`
    - Restart Anki to enable the API (listens on `127.0.0.1:8765`).

## Installation

### Quick Install

It is recommended to install the tool in a virtual environment.

```bash
# Clone the repository
git clone https://github.com/mrMaxwellTheCat/Anki-python-deck-tool.git
cd Anki-python-deck-tool

# Create and activate a virtual environment
python -m venv venv

# On Windows:
.\venv\Scripts\activate

# On Linux/Mac:
source venv/bin/activate

# Install the package
pip install .
```

### Development Installation

For contributing or development work:

```bash
# Install in editable mode with development dependencies
pip install -e ".[dev]"

# Or use the Makefile
make dev

# Set up pre-commit hooks (optional but recommended)
pre-commit install
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development setup instructions.

## Quick Start

Here's a minimal example to get you started:

1. **Create a single YAML file** (`my_deck.yaml`) with both configuration and data:

   ```yaml
   config:
     name: "Basic Model"
     deck-name: "French Basics"
     css: ".card { font-family: arial; font-size: 20px; text-align: center; }"
     fields:
       - "Front"
       - "Back"
     templates:
       - name: "Card 1"
         qfmt: "{{Front}}"
         afmt: "{{FrontSide}}<hr id=answer>{{Back}}"

   data:
     - front: "Hello"
       back: "Bonjour"
       tags: ["basics", "greetings"]

     - front: "Goodbye"
       back: "Au revoir"
       tags: ["basics"]
   ```

2. **Build the deck**:

   ```bash
   anki-yaml-tool build --file my_deck.yaml --output french.apkg
   ```

3. **Push to Anki** (optional, requires AnkiConnect):
   ```bash
   anki-yaml-tool push --apkg french.apkg --sync
   ```

## Building Executable

To compile the tool into a single executable file:

```bash
make build-exe
```

The resulting executable will be located in the `dist/` directory.

### Customizing the Icon

To use a custom icon for the executable, place your icon file in the `assets/` directory at the project root.

- **Windows**: `assets/icon.ico`
- **Mac**: `assets/icon.icns`

If these files exist, the build process will automatically use them.

### Installing System-Wide

After building the executable, you can install it system-wide to use `anki-yaml-tool` from anywhere in your terminal.

#### Using VS Code Tasks (Recommended)

1. Open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P)
2. Select "Tasks: Run Task"
3. Choose "Build and Install System-Wide"

This will build the executable and install it automatically.

#### Manual Installation

**Windows (PowerShell):**

```powershell
# Build the executable first
make build-exe

# Install system-wide
powershell -ExecutionPolicy Bypass -File scripts/install-system-wide.ps1
```

**Linux/macOS (Bash):**

```bash
# Build the executable first
make build-exe

# Install system-wide
bash scripts/install-system-wide.sh
```

The installation script will:

- Copy the executable to a standard location:
  - **Windows**: `%LOCALAPPDATA%\Programs\anki-yaml-tool`
  - **Linux/macOS**: `~/.local/bin/`
- Add the installation directory to your PATH if needed
- Guide you through any required terminal restarts

After installation, you can run `anki-yaml-tool` from any directory in your terminal.

## Usage

The tool provides a CLI entry point `anki-yaml-tool` with two main commands: `build` and `push`.

### 1. Build a Deck (`build`)

Generates an `.apkg` file from your YAML data and configuration.

```bash
anki-yaml-tool build --file my_deck.yaml --output "My Deck.apkg"
```

**Options:**

- `--file PATH` (Required): Path to a YAML file containing both `config` and `data` sections.
- `--output PATH`: Path where the `.apkg` will be saved (Default: `deck.apkg`).

**Examples:**

```bash
# Basic usage
anki-yaml-tool build --file my_deck.yaml --output "My Deck.apkg"

# Building multiple decks
anki-yaml-tool build --file decks/vocabulary.yaml --output builds/vocabulary_v1.apkg
anki-yaml-tool build --file decks/grammar.yaml --output builds/grammar_v1.apkg
```

### 2. Push to Anki (`push`)

Uploads a generated `.apkg` file to Anki via AnkiConnect.

```bash
anki-yaml-tool push --apkg "My Deck.apkg" --sync
```

**Options:**

- `--apkg PATH` (Required): Path to the `.apkg` file.
- `--sync`: Force a synchronization with AnkiWeb after importing.

**Note**: Ensure Anki is running with the AnkiConnect add-on enabled before using the `push` command.

## File Formats

The tool uses a single YAML file format containing both `config` and `data` sections. This provides a simple, organized structure for managing your Anki decks.

**Example: `my_deck.yaml`**

```yaml
config:
  name: "Japanese Numbers Model" # Name of the Note Type in Anki
  deck-name: "Japanese Numbers" # Name of the deck in Anki
  media-folder: "./media/" # Optional: Path to media files

  css: |
    .card {
     font-family: arial;
     font-size: 20px;
     text-align: center;
     color: black;
     background-color: white;
    }
    .highlight { color: red; }

  fields:
    - "Numeral"
    - "Kanji"
    - "Reading"

  templates:
    - name: "Card 1: Numeral -> Kanji"
      qfmt: "{{Numeral}}" # Front side HTML
      afmt: | # Back side HTML
        {{FrontSide}}
        <hr id=answer>
        {{Kanji}}<br>
        <span class="highlight">{{Reading}}</span>

data:
  - numeral: "1"
    kanji: "一"
    reading: "ichi"
    tags:
      - "basic"
      - "numbers"
    id: "num_001" # Optional: Adds an 'id::num_001' tag

  - numeral: "2"
    kanji: "二"
    reading: "ni"
    tags: ["basic"]

  - numeral: "3"
    kanji: "三"
    reading: "san"
    tags: ["basic", "numbers"]
```

**Config Section Fields:**

- `name` (required): Name of the note type/model in Anki
- `deck-name` (required): Name of the deck in Anki
- `fields` (required): List of field names for the note type
- `templates` (required): List of card templates with `name`, `qfmt` (front), and `afmt` (back)
- `css` (optional): CSS styling for the cards
- `media-folder` (optional): Path to folder containing media files (images, audio, etc.)

**Data Section Structure:**

- Each item in the list represents one note/card
- Keys should match field names from the config (case-insensitive)
- `tags` (optional): List of tags to apply to the note
- `id` (optional): Unique identifier that gets added as a special tag (`id::value`)

**Tips:**

- Field values can contain HTML for formatting
- Missing fields will be filled with empty strings
- Tags help organize and filter cards in Anki

## Project Structure

```
Anki-python-deck-tool/
├── .github/
│   ├── workflows/
│   │   ├── ci.yml              # CI pipeline (lint, type-check, test)
│   │   └── release.yml         # Release automation
│   └── copilot-instructions.md # Instructions for GitHub Copilot
├── configs/                     # Example configuration files
│   └── debug_config.yaml
├── data/                        # Example data files
│   └── debug_deck.yaml
├── src/
│   └── anki_yaml_tool/
│       ├── __init__.py
│       ├── cli.py               # CLI entry points
│       └── core/
│           ├── __init__.py
│           ├── builder.py       # Deck building logic
│           ├── connector.py     # AnkiConnect integration
│           └── exceptions.py    # Custom exception classes
├── tests/                       # Test suite
│   ├── __init__.py
│   ├── test_builder.py
│   ├── test_connector.py
│   └── test_exceptions.py
├── .gitignore
├── .pre-commit-config.yaml      # Pre-commit hooks configuration
├── CONTRIBUTING.md              # Development guidelines
├── LICENSE
├── Makefile                     # Common development tasks
├── README.md
├── ROADMAP.md                   # Future development plans
├── pyproject.toml               # Project metadata and tool configs
└── requirements.txt             # Project dependencies
```

## Development

This project welcomes contributions! For detailed setup instructions, coding standards, and workflow guidelines, please see [CONTRIBUTING.md](CONTRIBUTING.md).

### Quick Development Setup

```bash
# Install in development mode
pip install -e ".[dev]"

# Run tests
make test

# Format code
make format

# Lint code
make lint

# Type check
make type-check

# Run all checks
make all
```

### Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=anki_yaml_tool

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

## Future Plans

- **Media Support**: Enhance media file handling (basic `add_media()` support exists).
- **Schema Validation**: Validate YAML structure using pydantic for better error messages.
- **Multiple Note Types**: Support multiple note types in a single deck build.
- **Verbose Logging**: Add `--verbose` flag for detailed logging.
- **Init Command**: Scaffold new projects with example files (`anki-yaml-tool init`).
- **GUI Interface**: Graphical interface for users who prefer not to use the command line.
- **Enhanced Distribution**: Create installers and distribution packages beyond basic executables.

See [ROADMAP.md](ROADMAP.md) for the complete development roadmap.

## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:

- Development environment setup
- Code style guidelines
- Testing requirements
- Pull request process

## License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

## Acknowledgments

- Built with [genanki](https://github.com/kerrickstaley/genanki) for Anki package generation
- Uses [AnkiConnect](https://foosoft.net/projects/anki-connect/) for Anki integration
- CLI powered by [Click](https://click.palletsprojects.com/)

---

**Note**: This tool is not affiliated with or endorsed by Anki or AnkiWeb.
