Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/yannickfunk/genanki-rs
Rust crate to create Anki decks. Based on the python library genanki
https://github.com/yannickfunk/genanki-rs
anki anki-flashcards flashcards genanki rust
Last synced: 22 days ago
JSON representation
Rust crate to create Anki decks. Based on the python library genanki
- Host: GitHub
- URL: https://github.com/yannickfunk/genanki-rs
- Owner: yannickfunk
- License: mit
- Created: 2021-05-01T15:45:58.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2024-07-30T06:44:16.000Z (3 months ago)
- Last Synced: 2024-10-01T09:42:33.550Z (about 1 month ago)
- Topics: anki, anki-flashcards, flashcards, genanki, rust
- Language: Rust
- Homepage:
- Size: 65.4 KB
- Stars: 103
- Watchers: 2
- Forks: 20
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# genanki-rs: A Rust Crate for Generating Anki Decks
With `genanki-rs` you can easily generate decks for the popular open source flashcard platform Anki.
*The code of this library is based on the code of [`genanki`](https://github.com/kerrickstaley/genanki), a python library to generate Anki decks.*
*This library and its author(s) are not affiliated/associated with the main Anki project in any way.*
![example workflow](https://github.com/yannickfunk/genanki-rs/actions/workflows/rust.yml/badge.svg)
## Contribution
Contributions in any form are welcome! Feel free to just create an Issue or a PR.## How to use (Use the [`documentation`](https://docs.rs/genanki-rs/0.4.0/genanki_rs/index.html) for further information)
Add
```toml
[dependencies]
genanki-rs = "0.4"
```
to your `Cargo.toml` or find another version on [*crates.io*](https://crates.io/crates/genanki-rs)## Notes
The basic unit in Anki is the `Note`, which contains a fact to memorize. `Note`s correspond to one or more `Card`s.Here's how you create a `Note`:
```rust
use genanki_rs::{Note, Error};fn main() -> Result<(), Error> {
// let my_model = ...
let my_note = Note::new(my_model, vec!["Capital of Argentina", "Buenos Aires"])?;
Ok(())
}
```You pass in a `Model`, discussed below, and a set of `fields` (encoded as HTML).
## Models
A `Model` defines the fields and cards for a type of `Note`. For example:```rust
use genanki_rs::{Field, Model, Template, Error};fn main() -> Result<(), Error> {
let my_model = Model::new(
1607392319,
"Simple Model",
vec![Field::new("Question"), Field::new("Answer")],
vec![Template::new("Card 1")
.qfmt("{{Question}}")
.afmt(r#"{{FrontSide}}
{{Answer}}"#)],
);
// let my_note = ...
Ok(())
}
```This note-type has two fields and one card. The card displays the `Question` field on the front and the `Question` and
`Answer` fields on the back, separated by a `
`. You can also pass custom `css` by calling `Model::css()` to supply custom
CSS.```rust
let custom_css = ".card {\n font-family: arial;\n font-size: 20px;\n text-align: center;\n color: black;\n}\n";
let my_model_with_css = Model::new(
1607392319,
"Simple Model",
vec![Field::new("Question"), Field::new("Answer")],
vec![Template::new("Card 1")
.qfmt("{{Question}}")
.afmt(r#"{{FrontSide}}
{{Answer}}"#)])
.css(custom_css);
```You need to pass a model `id` and a model `name` so that Anki can keep track of your model. It's important that you use a unique model `id`
for each `Model` you define.## Generating a Deck/Package
To import your notes into Anki, you need to add them to a `Deck`:```rust
use genanki_rs::{Deck, Error};fn main() -> Result<(), Error> {
// let my_note = ...
let mut my_deck = Deck::new(
2059400110,
"Country Capitals",
"Deck for studying country capitals",
);
my_deck.add_note(my_note);
Ok(())
}
```Once again, you need a unique deck `id`, a deck `name` and a deck `description`.
Then, create a `Package` for your `Deck` and write it to a file:
```rust
my_deck.write_to_file("output.apkg")?;
```You can then load `output.apkg` into Anki using File -> Import...
## Media Files
To add sounds or images, create a `Package` and pass the `decks` and `media_files` you want to include:```rust
use genanki_rs::{Deck, Error, Package};fn main() -> Result<(), Error> {
// ...
// my_deck.add(my_note)
let mut my_package = Package::new(vec![my_deck], vec!["sound.mp3", "images/image.jpg"])?;
my_package.write_to_file("output.apkg")?;
Ok(())
}
````media_files` should have the path (relative or absolute) to each file. To use them in notes, first add a field to your model, and reference that field in your template:
```rust
let my_model = Model::new(
1607392319,
"Simple Model",
vec![
Field::new("Question"),
Field::new("Answer"),
Field::new("MyMedia"), // ADD THIS
],
vec![Template::new("Card 1")
.qfmt("{{Question}}{{Question}}
{{MyMedia}}") // AND THIS
.afmt(r#"{{FrontSide}}
{{Answer}}"#)],
);
```Then, set the `MyMedia` field on your `Note` to `[sound:sound.mp3]` for audio and `` for images (e.g):
```rust
let my_note = Note::new(my_model, vec!["Capital of Argentina", "Buenos Aires", "[sound:sound.mp3]"])?;
// or
let my_note = Note::new(my_model, vec!["Capital of Argentina", "Buenos Aires", r#""#])?;
```You *cannot* put `` in the template and `image.jpg` in the field. See these sections in the Anki manual for more information: [Importing Media](https://docs.ankiweb.net/#/importing?id=importing-media) and [Media & LaTeX](https://docs.ankiweb.net/#/templates/fields?id=media-amp-latex).
You should only put the filename (aka basename) and not the full path in the field; `` will *not* work. Media files should have unique filenames.
## sort_field
Anki has a value for each `Note` called the `sort_field`. Anki uses this value to sort the cards in the Browse
interface. Anki also is happier if you avoid having two notes with the same `sort_field`, although this isn't strictly
necessary. By default, the `sort_field` is the first field, but you can change it by calling `Note::sort_field()`.You can also call `Model::sort_field_index()`, passing the `sort_field_index` to change the sort field. `0` means the first field in the Note, `1` means the second, etc.
## FAQ
### My field data is getting garbled
If fields in your notes contain literal `<`, `>`, or `&` characters, you need to HTML-encode them: field data is HTML, not plain text.For example, you should write
```rust
let fields = vec!["AT&T was originally called", "Bell Telephone Company"]
```This applies even if the content is LaTeX; for example, you should write
```rust
let fields = vec!["Piketty calls this the \"central contradiction of capitalism\".", "[latex]r > g[/latex]"]
```