Skip to main content

Convert Markdown formatted documents to anki decks

Project description

md2anki

Convert Markdown formatted documents to anki decks

PyPI version

The decks were tested on:

Features

  • Create an anki deck .apkg file

  • The name of the deck and its notes will be updated on your next deck import (this works via automatic IDs, deletions can not be tracked!)

  • Very simple basic structure that supports additionally anki note tags and anki subdecks:

  • Supported question/answer content:

    • LaTeX math (inline and blocks)
    • Images (local files and URLs, vector and raster format)
    • Code (inline and blocks)
    • All basic Markdown features (i.e. tables, bold, italics, lines)
  • Merge notes from multiple markdown input files into a single deck output file

  • Export document and all used local assets to a custom directory that can easily be shared or used as backup

To evaluate code and export to pdf the following additional software needs to be installed:

# Linux
# > Ubuntu
# >> Evaluate code
sudo apt install clang inkscape latexmk nodejs texlive texlive-latex-extra #texlive-full
# >> PDF export
sudo apt install librsvg2-bin pandoc texlive-xetex
# > Arch/Manjaro
# Manjaro/Arch Linux
# >> Evaluate code
sudo pacman -S swi-prolog clang npm inkscape
# >> PDF export
sudo pacman -S pandoc-cli texlive-latex texlive-binextra texlive-xetex texlive-latexextra texlive-fontsextra texlive-luatex texlive-fontsrecommended
# Windows (the choco package manager is just an example)
# > Evaluate code
choco install inkscape llvm miktex nodejs
# > PDF export
choco install miktex pandoc rsvg-convert

(On Windows rsvg-convert can sometimes throw errors in combination with pandoc but the latest build from miyako does not throw them so try this one if you get errors)

# Linux + Windows
npm install -g ts-node
# > For matplotlib python graphs (used in some examples):
python -m pip install numpy matplotlib

Examples

# Example 'Basic' (3714486828)

## One line question (66b3661f-e22e-4986-a50d-569fdac454ad)

One line answer

## Multi line (24501c1a-f615-4355-a862-a00f64cc4725)

question thanks to a question answer separator (`---`)

---

Answer that has multiple lines.

**Basic** *Markdown* and <ins>HTML</ins> <del>formatting</del> is supported.

List:

- a
- b
  - c
  - d
    - e

New list:

1. abc
2. def
   - a
     1. maximum depth

## Question with multiple (parenthesis) (is) (possible) (b7b85393-b76d-43e6-965a-d86108bf5b09)

Answer

## Lines in answers with multiple `---` (f0e03cb6-2015-4f64-bcd3-51e24763705b)

First question answer seperator in the question.

---

Answer

---

Second part of answer with a line before it.
# Example 'Subdeck' (750441971)

Example document to show how subdecks work.

`{=:global_tag:=}`

## Question 1 (f51d6aa5-1e39-4ad7-94fb-042f7084eff5)

Answer

## Subdeck: Subdeck Heading 1 (406542328)

All notes of the level 3 will be added to this subdeck.

`{=:subdeck_tag_1:=}`

### Question 1.1 (583813da-5766-4cb8-b39f-ae0337e1f13c)

Answer

## Question 1.2 (f51d6aa5-1e39-4ad8-94fb-047f7094eff5)

Answer

## Subdeck: Subdeck Heading 2 (406541128)

`{=:subdeck_tag_2:=}`

### Question 2.1 (583813da-5766-4cb8-b39f-ae0337e1f13c)

Answer

### Subdeck: Subdeck Heading 3 with escaped :​: double colon (406641128)

All notes of the level 4 will be added to this subdeck.

`{=:subdeck_subdeck_tag:=}`

#### Question 3.1 (583813da-5786-4cb8-b39f-ae0337e1f13c)

Answer

### Question 2.2 (583223da-5786-4cb8-b39f-ae0337e1f13c)

Answer

To create Fill in the blanks Anki cards you need to change the anki model:

md2anki document.md -o-anki anki_deck.apkg -anki-model md2anki_type_cloze

If you select the md2anki_type_cloze_extra model the "extra" part below "---" will also be displayed only on the answer page while on the md2anki_type_cloze model it will just show it on the question and answer part:

md2anki document.md -o-anki anki_deck.apkg -anki-model md2anki_type_cloze_extra
# Example 'Fill in the Blank' (3083273130)

## Basic fill in the blank (5afd1da8-f5af-4abd-8809-6e3e47d164eb)

This text is {{c1::boring::a custom hint}} and {{c1::a placeholder}}

---

This will create be displayed as:

- This text is [a custom hint] and [...]
- This text is boring and a placeholder

## Multiple fill the blanks (7e0c3a24-a542-4b53-84c2-0481caa86ab4)

{{c1::Mitochondria}} are the {{c2::powerhouses}} of the cell

---

This will create 2 cards and be displayed as:

- [...] are the powerhouses of the cell
- Mitochondria are the [...] of the cell

which both become:

- Mitochondria are the powerhouses of the cell

The anki models can be mixed together and even specified on the card:

# Global model md2anki_type_cloze
# - contains one md2anki_type_cloze (global override)
# - contains one md2anki_type_default (override on card)
# - contains one md2anki_type_cloze_extra (override on card)
md2anki document.md -o-anki anki_deck.apkg
# Example 'Multiple card types' (2303117446)

Global card type:

`{=<md2anki_type_cloze>=}`

## Card with global {{c1::card type}} (680d8091-21fb-40e0-9b9b-314b93baafcf)

Answer

## Card with custom card type `{=<md2anki_type_default>=}` (888ca2b8-9191-49fb-9681-bd5d818b5749)

Answer

## {{c1::Multi}} line card with custom card type (0834581b-ad90-47c1-b6ba-fc884e582d87)

`{=<md2anki_type_cloze_extra>=}`

---

Answer

Checkout the examples directory for more examples.

If you want to run them all use the following command in that directory:

python -m examples

Usage

usage: md2anki [-h] [-v] [--lexers] [-d [{DEBUG,INFO,WARNING,ERROR,CRITICAL}]] [-e]
               [--evaluate-code-ignore-cache] [--evaluate-code-delete-cache] [-k]
               [-anki-model MODEL_ID] [-o-anki APKG_FILE] [-o-md MD_FILE] [-o-md-dir MD_DIR]
               [-o-backup-dir BACKUP_DIR] [-o-pdf PDF_FILE] [-evaluate-code-cache-dir CACHE_DIR]
               [-log-file LOG_FILE] [-file-dir [FILE_DIR ...]] [-md-heading-depth HEADING_DEPTH]
               [-custom-program language program] [-custom-program-args language program-args]
               MD_INPUT_FILE [MD_INPUT_FILE ...]

Create an anki deck file (.apkg) from one or more Markdown documents. If no custom output path is
given the file name of the document (+ .apkg) is used.

positional arguments:
  MD_INPUT_FILE         Markdown (.md) input file that contains anki deck notes

options:
  --evaluate-code-delete-cache
                        delete all cached files from previous code evaluations (default: False)
  --evaluate-code-ignore-cache
                        ignore the cached files from previous code evaluations (default: False)
  --lexers              print a list of all supported lexer languages and their aliases
  -anki-model MODEL_ID  custom anki card model (md2anki_type_default, md2anki_type_answer,
                        md2anki_type_cloze, md2anki_type_cloze_extra) (default: md2anki_type_default)
  -custom-program language program
                        use custom program for code evaluation [i.e. "py" "python3.11"] (default:
                        [('py', 'python'), ('js', 'node'), ('ts', 'npx'), ('pl', 'swipl'), ('latex',
                        'latexmk'), ('latex', 'inkscape'), ('cpp', 'clang++'), ('cpp', 'main.exe'),
                        ('c', 'clang'), ('c', 'main.exe'), ('pandoc_pdf', 'pandoc')])
  -custom-program-args language program-args
                        use custom program args for code evaluation [i.e. "py"
                        "[\"-c\",\"MD2ANKI_CODE\"]"] (default: [('py', '["-c", "MD2ANKI_CODE"]'),
                        ('js', '["-e", "MD2ANKI_CODE"]'), ('ts', '["tsx",
                        "MD2ANKI_CODE_FILE=code.ts"]'), ('pl', '["-O", "-s",
                        "MD2ANKI_CODE_FILE=code.pl", "-g", "true", "-t", "halt."]'), ('latex',
                        '["-shell-escape", "-pdf", "MD2ANKI_CODE_FILE=code.tex"]'), ('latex', '["--
                        export-filename=code.svg", "code.pdf"]'), ('cpp', '["-Wall", "-std=c++20",
                        "MD2ANKI_CODE_FILE=main.cpp", "-o", "main.exe"]'), ('cpp', '[]'), ('c',
                        '["-std=c17", "MD2ANKI_CODE_FILE=main.c", "-o", "main.exe"]'), ('c', '[]'),
                        ('pandoc_pdf', '["--from", "markdown", "--to", "pdf", "--table-of-contents",
                        "-V", "geometry:a4paper", "-V", "geometry:margin=2cm", "--pdf-
                        engine=xelatex", "--pdf-engine-opt=-shell-escape"]')])
  -d, --debug [{DEBUG,INFO,WARNING,ERROR,CRITICAL}]
                        custom log level to the console (default: INFO)
  -e, --evaluate-code   evaluate markdown inline code/code blocks with the language prefix '=' i.e.
                        '`print(1+1)`{=python}' or '```{=python} [newline] print(1+1) [newline] ```'
                        (default: False)
  -evaluate-code-cache-dir CACHE_DIR
                        use a custom cache dir for code evaluations (default: None)
  -file-dir [FILE_DIR ...]
                        add directories that should be checked for referenced files (like relative
                        path images) (default: [])
  -h, --help            show this help message and exit
  -k, --keep-temp-files
                        keep temporary files (default: False)
  -log-file LOG_FILE    log all messages to a text file (.log) (default: None)
  -md-heading-depth HEADING_DEPTH
                        use a custom Markdown heading depth (>=1) (default: 1)
  -o-anki APKG_FILE     custom anki deck (.apkg) output file path [if not given: md input file name +
                        .apkg] (default: None)
  -o-backup-dir BACKUP_DIR
                        create a backup of the anki deck (i.e. merges input files and copies external
                        files) in a directory (default: None)
  -o-md MD_FILE         custom updated (and merged if multiple input files) Markdown (.md) output
                        file path for all input files (default: None)
  -o-md-dir MD_DIR      custom output directory for all updated Markdown (.md) input files (default:
                        None)
  -o-pdf PDF_FILE       create a PDF (.pdf) file of the anki deck (i.e. merges input files and
                        removes IDs) (default: None)
  -v, --version         show program's version number and exit

Linux (bash)

# Single source file
md2anki anki_deck.md -o-anki anki_deck.apkg
# Multiple source files
md2anki *.md -o-anki anki_deck.apkg

Windows (powershell)

# Single source file
md2anki anki_deck.md -o-anki anki_deck.apkg
# Multiple source files
md2anki (Get-ChildItem -Filter *.md) -o-anki anki_deck.apkg

Install

PyPI

It can be installed using pip:

# Install
pip install md2anki
# Uninstall
pip uninstall md2anki

GitHub Releases

  1. Download a wheel (.whl) file from GitHub Releases

  2. Run:

    # Install
    pip install md2anki-$CURRENT_VERSION-py3-none-any.whl
    # Uninstall
    pip uninstall md2anki
    

Pacman

cd pkgbuild
# Build package and then install it via pacman
makepkg -p PKGBUILD --syncdeps --rmdeps --clean
pacman -S python-md2anki-3.0.19b-1-any.pkg.tar.zst
# Or build and install package
makepkg -p PKGBUILD --syncdeps --rmdeps --clean --install
# Remove package
pacman -R python-md2anki

Build

Via the file setup.py the package can be built:

Create package files

The following commands create the package files in a new directory called dist:

  • md2anki-$CURRENT_VERSION-py3-none-any.whl
  • md2anki-$CURRENT_VERSION.tar.gz
python -m pip install --upgrade build
python -m build

Install package files

The wheel (.whl) file can be installed and uninstalled via pip:

# Install
python -m pip install dist/md2anki-$CURRENT_VERSION-py3-none-any.whl
# Uninstall
python -m pip uninstall md2anki

Markdown Editors

A list of editors which support WYSIWYG editing of such Markdown documents (source code and math blocks):

Development

Dependencies

python -m pip install --upgrade pip
# Runtime dependencies
python -m pip install --upgrade beautifulsoup4 genanki Markdown Pygments
# Save requirements
python -m pip freeze > "requirements.txt"

Upload package to PyPI

  1. Create an PyPI account
  2. Go to account settings, Scroll to API tokens, Create PyPI API token (with only the project scope if project already exists)
# Build
python -m pip install --upgrade pip build
python -m build
# Upload (only if a non existing version is found)
python -m pip install twine
python -m twine upload --skip-existing dist/*
# Use as username: "__token__"
# Use as password the created PyPI API token: "pypi-......"

Type checks

Python files can be checked for type errors (to some extent) using the commands:

python -m pip install --upgrade mypy types-beautifulsoup4 types-Markdown types-Pygments types-setuptools
python -m mypy src setup.py examples tests clean.py main.py update_readme.py update_pkgbuild.py format.py

Tests

The tests can be run using the command (in the tests directory):

python -m unittest

Format code

Python files can be formatted using the commands:

python -m pip install --upgrade black
# Add the option --check to only check if its already in the correct format
python -m black src setup.py examples tests clean.py main.py update_readme.py

Code editors

This project was written using the following code editors (IDEs):

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

md2anki-3.1.0.tar.gz (48.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

md2anki-3.1.0-py3-none-any.whl (44.7 kB view details)

Uploaded Python 3

File details

Details for the file md2anki-3.1.0.tar.gz.

File metadata

  • Download URL: md2anki-3.1.0.tar.gz
  • Upload date:
  • Size: 48.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for md2anki-3.1.0.tar.gz
Algorithm Hash digest
SHA256 2deb8d08f683bb99f04a5de0a28c66bb25a09ad6bf09be933e168d3471866782
MD5 d68198eedbddb1552b82384314686e3c
BLAKE2b-256 dc1c91e62ed23c0e84bc7eb9ebcd1702f318c3e7e18ee3cd08cb0adacaa3bd46

See more details on using hashes here.

File details

Details for the file md2anki-3.1.0-py3-none-any.whl.

File metadata

  • Download URL: md2anki-3.1.0-py3-none-any.whl
  • Upload date:
  • Size: 44.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for md2anki-3.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 55c554d1823ddb8d1e3a3801b2e673df78bb2170d30ee7c94c1219ffc0373dbb
MD5 98680f0c89e9e426b1930633f6cfe143
BLAKE2b-256 dd2574de078d7751d4be136339d35b2527fcde29eb5d2d8130a2a2a0aeb71dfa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page