diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-19 18:30:47 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-19 18:30:47 -0500 |
| commit | a143679a50f5d3a84aea3ed4effcb3ac9e5af69f (patch) | |
| tree | fa2545427bdafdbdce2fe3205c01f23f609e30c2 /languages/python/tests | |
| parent | b3195e9e55e185281d4d965333b1ad4ebb2ca6ee (diff) | |
| download | rulesets-a143679a50f5d3a84aea3ed4effcb3ac9e5af69f.tar.gz rulesets-a143679a50f5d3a84aea3ed4effcb3ac9e5af69f.zip | |
feat(flashcard): add apkg-to-orgdrill.py, the inverse of flashcard-to-anki
The flashcard pipeline was one-directional (org-drill to apkg). A deck curated on the phone, or an orphaned apkg whose org source was never saved, had no way back into the org source of truth. apkg-to-orgdrill.py closes the loop.
An apkg is a zip holding an Anki sqlite collection, so reading it needs no third-party library: stdlib zipfile + sqlite3. genanki is only needed to write apkgs, not read them, so the converter has no runtime deps. It mirrors flashcard-to-anki.py inverted: deck name to #+TITLE, note Front to the ** heading, note Back HTML to the body (<br> to newlines, entities unescaped, the answer <hr> stripped), the note tag to a * section, and a fresh :ID: UUID per card so the output is org-drill-valid.
The entity unescape runs in the order that inverts escape_html, which escaped & first, so & is unescaped last here. Otherwise a literally-escaped < in the source would wrongly collapse to <. Only Front/Back note types convert; a cloze or other model is skipped with a warning rather than silently dropped, and a note referencing media is flagged since the org side has no media path.
17 tests cover the HTML-to-org conversion, the apkg read (single and multiple decks, Default-deck exclusion, non-basic skip, .anki2 vs .anki21, media flag), the org emission, and errors. The round-trip test closes the loop through flashcard-to-anki.py's own parse(): a known org source becomes an apkg fixture, converts back, and the recovered (front, back, tag) tuples match the original. Verified end to end against a real genanki-produced apkg too.
Diffstat (limited to 'languages/python/tests')
0 files changed, 0 insertions, 0 deletions
