{"id":15017277,"url":"https://github.com/yannickfunk/genanki-rs","last_synced_at":"2025-09-08T12:34:23.246Z","repository":{"id":47789938,"uuid":"363447269","full_name":"yannickfunk/genanki-rs","owner":"yannickfunk","description":"Rust crate to create Anki decks. Based on the python library genanki","archived":false,"fork":false,"pushed_at":"2024-07-30T06:44:16.000Z","size":67,"stargazers_count":115,"open_issues_count":7,"forks_count":23,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-29T20:05:57.069Z","etag":null,"topics":["anki","anki-flashcards","flashcards","genanki","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yannickfunk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-01T15:45:58.000Z","updated_at":"2025-03-01T06:48:48.000Z","dependencies_parsed_at":"2024-09-20T14:30:27.457Z","dependency_job_id":null,"html_url":"https://github.com/yannickfunk/genanki-rs","commit_stats":{"total_commits":68,"total_committers":4,"mean_commits":17.0,"dds":0.05882352941176472,"last_synced_commit":"fe983cf519e727f8265f920f61e6c06ffe94bee4"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickfunk%2Fgenanki-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickfunk%2Fgenanki-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickfunk%2Fgenanki-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannickfunk%2Fgenanki-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yannickfunk","download_url":"https://codeload.github.com/yannickfunk/genanki-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399879,"owners_count":20932880,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anki","anki-flashcards","flashcards","genanki","rust"],"created_at":"2024-09-24T19:50:14.990Z","updated_at":"2025-04-05T21:09:44.918Z","avatar_url":"https://github.com/yannickfunk.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# genanki-rs: A Rust Crate for Generating Anki Decks\n\nWith `genanki-rs` you can easily generate decks for the popular open source flashcard platform Anki.\n\n*The code of this library is based on the code of [`genanki`](https://github.com/kerrickstaley/genanki), a python library to generate Anki decks.*\n\n*This library and its author(s) are not affiliated/associated with the main Anki project in any way.*\n\n![example workflow](https://github.com/yannickfunk/genanki-rs/actions/workflows/rust.yml/badge.svg)\n\n## Contribution\nContributions in any form are welcome! Feel free to just create an Issue or a PR.\n\n## How to use (Use the [`documentation`](https://docs.rs/genanki-rs/0.4.0/genanki_rs/index.html) for further information)\nAdd\n```toml\n[dependencies]\ngenanki-rs = \"0.4\"\n```\nto your `Cargo.toml` or find another version on [*crates.io*](https://crates.io/crates/genanki-rs)\n\n## Notes\nThe basic unit in Anki is the `Note`, which contains a fact to memorize. `Note`s correspond to one or more `Card`s.\n\nHere's how you create a `Note`:\n\n```rust\nuse genanki_rs::{Note, Error};\n\nfn main() -\u003e Result\u003c(), Error\u003e {\n    // let my_model = ...\n    let my_note = Note::new(my_model, vec![\"Capital of Argentina\", \"Buenos Aires\"])?;\n    Ok(())\n}\n```\n\nYou pass in a `Model`, discussed below, and a set of `fields` (encoded as HTML).\n\n## Models\nA `Model` defines the fields and cards for a type of `Note`. For example:\n\n```rust\nuse genanki_rs::{Field, Model, Template, Error};\n\nfn main() -\u003e Result\u003c(), Error\u003e {\n    let my_model = Model::new(\n        1607392319,\n        \"Simple Model\",\n        vec![Field::new(\"Question\"), Field::new(\"Answer\")],\n        vec![Template::new(\"Card 1\")\n            .qfmt(\"{{Question}}\")\n            .afmt(r#\"{{FrontSide}}\u003chr id=\"answer\"\u003e{{Answer}}\"#)],\n    );\n    // let my_note = ...\n    Ok(())\n}\n```\n\nThis note-type has two fields and one card. The card displays the `Question` field on the front and the `Question` and\n`Answer` fields on the back, separated by a `\u003chr\u003e`. You can also pass custom `css` by calling `Model::css()` to supply custom\nCSS.\n\n```rust\nlet custom_css = \".card {\\n font-family: arial;\\n font-size: 20px;\\n text-align: center;\\n color: black;\\n}\\n\";\nlet my_model_with_css = Model::new(\n    1607392319,\n    \"Simple Model\",\n    vec![Field::new(\"Question\"), Field::new(\"Answer\")],\n    vec![Template::new(\"Card 1\")\n        .qfmt(\"{{Question}}\")\n        .afmt(r#\"{{FrontSide}}\u003chr id=\"answer\"\u003e{{Answer}}\"#)])\n    .css(custom_css);\n```\n\nYou 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`\nfor each `Model` you define.\n\n## Generating a Deck/Package\nTo import your notes into Anki, you need to add them to a `Deck`:\n\n```rust\nuse genanki_rs::{Deck, Error};\n\nfn main() -\u003e Result\u003c(), Error\u003e {\n    // let my_note = ...\n    let mut my_deck = Deck::new(\n        2059400110,\n        \"Country Capitals\",\n        \"Deck for studying country capitals\",\n    );\n    my_deck.add_note(my_note);\n    Ok(())\n}\n```\n\nOnce again, you need a unique deck `id`, a deck `name` and a deck `description`.\n\nThen, create a `Package` for your `Deck` and write it to a file:\n\n```rust\nmy_deck.write_to_file(\"output.apkg\")?;\n```\n\nYou can then load `output.apkg` into Anki using File -\u003e Import...\n\n## Media Files\nTo add sounds or images, create a `Package` and pass the `decks` and `media_files` you want to include:\n\n```rust\nuse genanki_rs::{Deck, Error, Package};\n\nfn main() -\u003e Result\u003c(), Error\u003e {\n    // ...\n    // my_deck.add(my_note)\n    let mut my_package = Package::new(vec![my_deck], vec![\"sound.mp3\", \"images/image.jpg\"])?;\n    my_package.write_to_file(\"output.apkg\")?;\n    Ok(())\n}\n```\n\n`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:\n\n```rust\nlet my_model = Model::new(\n    1607392319,\n    \"Simple Model\",\n    vec![\n        Field::new(\"Question\"),\n        Field::new(\"Answer\"),\n        Field::new(\"MyMedia\"),                           // ADD THIS\n    ],\n    vec![Template::new(\"Card 1\")\n        .qfmt(\"{{Question}}{{Question}}\u003cbr\u003e{{MyMedia}}\") // AND THIS\n        .afmt(r#\"{{FrontSide}}\u003chr id=\"answer\"\u003e{{Answer}}\"#)],\n);\n```\n\nThen, set the `MyMedia` field on your `Note` to `[sound:sound.mp3]` for audio and `\u003cimg src=\"image.jpg\"\u003e` for images (e.g):\n\n```rust\nlet my_note = Note::new(my_model, vec![\"Capital of Argentina\", \"Buenos Aires\", \"[sound:sound.mp3]\"])?;\n// or\nlet my_note = Note::new(my_model, vec![\"Capital of Argentina\", \"Buenos Aires\", r#\"\u003cimg src=\"image.jpg\"\u003e\"#])?;\n```\n\nYou *cannot* put `\u003cimg src=\"{MyMedia}\"\u003e` 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 \u0026 LaTeX](https://docs.ankiweb.net/#/templates/fields?id=media-amp-latex).\n\nYou should only put the filename (aka basename) and not the full path in the field; `\u003cimg src=\"images/image.jpg\"\u003e` will *not* work. Media files should have unique filenames.\n\n## sort_field\nAnki has a value for each `Note` called the `sort_field`. Anki uses this value to sort the cards in the Browse\ninterface. Anki also is happier if you avoid having two notes with the same `sort_field`, although this isn't strictly\nnecessary. By default, the `sort_field` is the first field, but you can change it by calling `Note::sort_field()`.\n\nYou 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.\n\n## FAQ\n### My field data is getting garbled\nIf fields in your notes contain literal `\u003c`, `\u003e`, or `\u0026` characters, you need to HTML-encode them: field data is HTML, not plain text.\n\nFor example, you should write\n```rust\nlet fields = vec![\"AT\u0026amp;T was originally called\", \"Bell Telephone Company\"]\n```\n\nThis applies even if the content is LaTeX; for example, you should write\n```rust\nlet fields = vec![\"Piketty calls this the \\\"central contradiction of capitalism\\\".\", \"[latex]r \u0026gt; g[/latex]\"]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannickfunk%2Fgenanki-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyannickfunk%2Fgenanki-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannickfunk%2Fgenanki-rs/lists"}