diff --git a/edu/api/decks.php b/edu/api/decks.php index 329b8fe..1b80975 100644 --- a/edu/api/decks.php +++ b/edu/api/decks.php @@ -18,6 +18,38 @@ if (get_method() === 'GET' && empty($segments[1])) { json_ok(['decks' => $stmt->fetchAll()]); } +// GET /api/decks/export-anki — download all cards as Anki TSV +if (get_method() === 'GET' && ($segments[1] ?? '') === 'export-anki') { + $stmt = $pdo->query(" + SELECT d.name AS deck_name, c.question, c.answer, c.level + FROM cards c JOIN decks d ON d.id = c.deck_id + ORDER BY d.sort_order, d.name, c.sort_order + "); + $cards = $stmt->fetchAll(); + + header('Content-Type: text/tab-separated-values; charset=utf-8'); + header('Content-Disposition: attachment; filename="sol2_training_anki_' . date('Y-m-d') . '.txt"'); + header('Cache-Control: no-cache'); + + // Clean markdown formatting for Anki: backticks -> , ** -> + function anki_format($text) { + $t = $text; + $t = preg_replace('/```(\w*)\n(.*?)```/s', '
$2
', $t); + $t = str_replace('`', '', $t); + $t = preg_replace('/\*\*(.+?)\*\*/', '$1', $t); + $t = str_replace("\n", '
', $t); + $t = str_replace("\t", ' ', $t); + return $t; + } + + foreach ($cards as $c) { + $q = anki_format($c['question']); + $a = anki_format($c['answer']); + echo $q . "\t" . $a . "\t" . 'Sol2-Training::' . $c['deck_name'] . "\t" . $c['level'] . "\n"; + } + exit; +} + // GET /api/decks/{slug} if (get_method() === 'GET' && !empty($segments[1])) { $stmt = $pdo->prepare("SELECT * FROM decks WHERE slug = :s"); diff --git a/edu/js/flashcards.js b/edu/js/flashcards.js index 4701b75..189b018 100644 --- a/edu/js/flashcards.js +++ b/edu/js/flashcards.js @@ -26,10 +26,13 @@ var Flashcards = { var total = decks.reduce(function(s, d) { return s + (d.card_count || 0); }, 0); var totalDue = decks.reduce(function(s, d) { return s + (parseInt(d.due) || 0); }, 0); - var h = '