Package: markdown2anki
Markdown2AnkiMarkdown2Anki is a Python script that allows you to easily format your cards using Markdown syntax, and then import them into Anki while retaining the structure you gave them.This tool supports code highlighting, clozes, and images, making it a versatile and convenient option for anyone looking to streamline their flashcard creation process.
Additionally, it offers support for Obsidian notes, allowing you to create links inside your cards that point to your vault's notes! 🌸Unleash the power of spaced repetition: Convert your Markdown notes into Anki flashcards for optimal learning.ChatGPT, when asked for a captivating description of this project.Table of contents (for GitHub)FeaturesTechnical featuresImagesInstallationInitial setupUsing fill the blanksUsageMarkdown formattingImporting cardsImporting imagesErrors and Bad cardsUsing clozesChanging themesNavigating the UI"Can't find any element..." query ErrorCreating a custom themeContributing and dev documentationThe reasons behind the projectTechnologies usedHopes for the futureVersioningLicenseClosing noteThis is an open-source free software, you can find it on:Github -https://github.com/Mochitto/Markdown2AnkiPyPi -https://pypi.org/project/markdown2ankiFeaturesWrite and format cards in Markdown: create cards in Markdown syntax and then import them into Anki while retaining their structure.Custom Note typesthat support split-screen, tabs, keyboard shortcuts, and mobile devices.No addons needed: The resulting cards are pure HTML and the note-type is CSS and JS, which work with vanilla Anki.Different themes: themes for both day and night modes, which are easily customizable. You cancheck them out here!Code highlighting(usingpygments).Support for clozesincluding those in code blocks.Support for imageswith automatic importing: the program can find the images you mention in your obsidian notes and copy them to your Anki's media folder.Support for Obsidian links and images: using[[Note.md|my Note]]and[[my_image.jpg]]-like markdown.Accessible config filethat can self-heal (usingType-Config): retaining as many custom configurations as possible even if the file is corrupted. This also ensures that if options are added with updates, your custom configuration will be retained.Helpful error messages and feedback.Backup files of your inputs, to help you retry in case something goes wrong.Funny and expressive emoji in the CLIto make the tool more engaging and enjoyable to use.Technical featuresExtensive python tests coverage: as of 2023-03-13, there are 108 tests for this tool to ensure its robustness and reliability.Modular structureto facilitate maintainability and contributions.Os agnostic: this tool can run on any operating system.Type-safe python and javascript.Type-safe user configuration: user configurations are validated and type-casted upon file-reading to ensure their accuracy and consistency.SMACSS methodology driven SASS/CSS, with BEM classes nomenclature: for organized and structured styling.Minified and bundled JS/CSSincluding themes, for efficient and fast performance in the "production" note type.Mobile first responsive CSS: to ensure it's fully responsive on all devices.High-level dev documentationto make it easier for contributions and maintenance.ImagesCLIVideo demo of the CLISplit-screenCode highlightingClozes supportSupports the addon "fill the blanks"Mobile (with light mode)Mobile versionClozes in mobileInstallationThis project is distributed usingpipviaPypi.
This means you need Python installed on your machine, you can get it here:https://www.python.org/downloads/IMPORTANT!: When installing, make sure to check theAdd python to PATHif on Windows/Mac.Once you have installed Python, you can write in the command line:python-mpipinstallMarkdown2AnkiAnd then you should be able to run:md2ankiThere is a guided setup on your first time running the app, which will help you get up and running :)Notice:This app uses emoji to give instant feedback to the user, depending on your terminal you might not be able to see them correctly.On windows you can use theWindows terminal.
On iOS and Linux they should be supported by default.You can also get all of the possible arguments for the script with:md2anki-hThe script will also let you know when there is a new update and point you to theCHANGELOG.mdfile, where you can read what has changed and decide if to update or not.You can update the package with:python-mpipinstall--upgradeMarkdown2AnkiAfter doing this, the app will ask you again the location of your program folder and update (or heal) your configuration if it is present; if not, it will create a new one.Initial setupDuring the initial setup process, you will be prompted to select a folder where the program will put its files.Once you will have confirmed the path to said folder, a configuration file namedmd2anki.config.iniwill be added to it.The configuration file holds all the information on each option, what it does and if it's required or not.Suggested:Among the options, you might want to set asimages out-folderyour Anki media folder; this option sets the folder where images are copied to when they are found in your notes; by setting it to your anki's media folder, images are automatically added to you Anki's database.You can learn more about Anki's folders here:https://docs.ankiweb.net/files.html#file-locationsThere will also be amarkdown2anki.apkgfile which contains the anki note types you will need when importing the cards.If you have Anki installed on your system, you should be able to just double-click the file to import it, and it will create a new deck with some template cards and the note types.You can learn more on.apkgfiles here:https://docs.ankiweb.net/exporting.html#deck-apkgUsing fill the blanksIf you would like to have "type-in" clozes, you can use this addon:fill the blanks addon.For it to work, you will need to duplicate theMarkdown2Anki - ClozeNote type and modify it by changing theFront sidefield to:{{type:cloze:Front}}.This is a video with how you can achieve this:Video Tutorial on how to modify a note typeUsageMarkdown input formattingTo ensure that your notes are properly recognized by the program, there are a few formatting requirements:Cards separatorCards must be separated by a horizontal rule using three dashes or more---.Notice:***do not work as cards separators, this is so that you can use*to define horizontal rules inside of your cards :)TabsA unique feature of this program is the ability to create tabs within your cards.Tabs are divided depending on the card side (front, back) and the tabs side (left window, right window).Front side tabs, unless removed with the-flag (more on this later), are retained when moving to the back side (aka. "flipping the card").Back side tabs are added after the front tabs, unless they replace one that has been removed.Tab Labels and flagsTab labels define the beginning of a tab and its content, and should be formatted as follows:## <flags> [<tab label>]Flags define where your tab goes (left or right side of the card, front or back side of the card).The possible flags are:FlagsMeaningFFront side of the cardBBack side of the cardLLeft tabs sideRRight tabs side-Only applied to Front tabs: removes the tab when switching to the back side+Only applied to Back tabs: replaces a removed front tab## BR [This is my tab]And this is its bodyNotice:Tab labels do not support Markdown formatting, such as bold text etc.Default values:Front andLeft flags are applied automatically, so you can leave them out.## [My tab]is the same as## FL [My tab]## B [My tab]is the same as## BL [My tab]## R [My tab]is the same as## FR [My tab]ExampleHere are two example cards to illustrate the formatting requirements:## - [Question]# A great addition to humanityWhat is the**name**of this funny cat?## Make sure you get it right.## R [Funny cat]![[bingus.png]]## +B [Answer]This is the magnificent Bingus.

---## [Complete the code]This is the code needed to reverse sort a list.```pythonmy_list=[3,5,2]# New listsorted_list={{C1::sorted}}(my_list,{{C1::True}})# In placemy_list.{{C1::sort}}(True)```The result:(This is using thefill the blanks addon)Importing your cardsOnce you have processed your cards, they will be divided in cards with clozes and cards without clozes.Those will become two.csvfiles:basic_anki_cards.csvandclozed_anki_cards.csv.To import these, you have to open up Anki and press the "Import File" in the lower side of the main menu, or, if you prefer, you can use "File>Import" from the menu in the top-left of the Anki app.After selecting the.csvfile, you have to let anki know that the separator used isComma, select the rightnote typeand the deck you wish the cards to be imported in.
Also make sure to allow HTML in the cards, as they need it to work correctly.This is a screenshot of how this could look in your Anki (Anki's UI can change depending on the OS it is running on):You can find more information on importing to Anki here:https://docs.ankiweb.net/importing.htmlImporting your imagesYou can import images automatically if you add the path to yourAnki media folderin the config file.Images that are already present won't be added twice and will be skipped (based on filename).If you prefer checking the images before importing them manually, you can point to another folder or leave the default one.Notice:when images are copied, they lose their metadata: this is due to security, as others' could read your images metadata if you were to share your cards, and for how the python library that handles the copying process is implemented.Hopefully, in the near future, the importing part will be made automatic by the addition ofAnkiConnectsupport.Errors and Bad cardsWhen there are errors in formatting, the app will let you know what went wrong and create aBad_cards.mdfile in your program folder.This will be a file of all of the "Bad cards" (cards that had a problem in them). The specific error for each card is added before the tabs, so that you can easily fix them.These, as other text added at the beginning of a card, before all the tabs labels, are considered comments, so you can leave them in.For example:❌ ERROR ❌ - A card without front tabs has been found.## B [My card]That is very cool ⭐

---

❌ ERROR ❌ - A tab without body has been found.## [Fast inverse square root]Some common card errors are:Forgetting the body of a tabLeaving the front-side of a card emptyRemoving a tab that contains a cloze in itSome common general errors are:The configuration file is missing a necessary option (such as yourvault's name)No cards were found in the input fileOnce you have fixed your bad cards, you can run the program withmd2anki -bfThis will automatically use theBad_cards.mdas input, if you prefer fixing the cards in that file instead of adding them to the main input file.Adebug_log.txtfile is also present in your program folder, which is created every time you run the program. This file contains more information on what happens when the program is running, the result of various processes, your configuration and so on.If you find a bug in the program, it would be of great help if you could add this file to your issues on GitHub.Privacy Notice:the log file has your configuration in it, as it can contain crucial information for debugging.If you don't want to share your paths or other information from it when making issues, you should search-and-replace that information with some fake one, while trying not to change their general structure.Using clozesYou can specify clozes in your markdown and they will be carried over to your anki cards. Whenever there is a word or sentence you'd like to have as a cloze, you can use Anki's formatting{{c<number>::<word>::<hint?>}}(notice the two colons, not just one).
Clozes will also work in code blocks.The number tells Anki what cloze to add to what card. This means that if you have C1, C2 and C3, there will be three cards created (this is a feature of Anki, not of Markdown2Anki), each missing the respective words.More on this here:https://docs.ankiweb.net/editing.html#cloze-deletionFor example:my_list=[3,5,2]# New listsorted_list={{C1::sorted}}(my_list,{{C1::True}})# In placemy_list.{{C1::sort}}(True)Result
Notice how all instances ofsortandTrueare turned into clozes, even if only specified once in the Markdown text.Changing ThemesThe default theme is mochitto's Rosé Pine theme, but there is also a catpuccin theme.You can find all the themes in thethemes folder.To use another theme, you can just copy the CSS from the file in the themes folder and paste it in your Note types' styling field.This can be found by accessingTools>Manage Note Types>(select your note type)>Cards(on the right)>Styling(on the left). TheToolsmenu is found in the top-left part of Anki's main menu.You can reference this:Video Tutorial showing how to access a card's styleYou can read more on how styling happens here:https://docs.ankiweb.net/templates/styling.htmlNavigating the UIThe custom User Interface of the note-type that comes with this project is focused on the concept of tabs.You can have side-by-side tabs and multiple tabs to toggle through.To navigate them, you can either click on the labels of non-active tabs to make them active (switch to them), and click an active tab to make it full-screen.This works also in mobile.There are also keyboard commands: you can select a tab with<alt>+<number of the tab>or⌥  + <number of the tab>(the number is displayed next to the tab label) to switch to that tab or make it full-screen, or you canTABbetween to navigate between them.For example,Alt+1will show the first tab if it's not-active, or make it full-screen if it's active.Notice: at times the hotkeys don't seem to work completely (maybe one tab is not accessible with<alt>); I'm working on understanding better how Anki handles HTML and Javascript, as it's a problem on how it handles changing between cards... The<tab>and<click>methods seem to be stable, so you can use those if this bug happens.I'm sorry about it...Query errorSometimes, you might come across a screen saying "ERROR: Couldn't find any element using the query [...]".This happens because, for some reason, Anki is not loading correctly the card or the script. This shouldn't happen often and I'm still trying to understand better the underlying reasons behind it, as they have to do with Anki's way of handling HTML and Javascript...It will likely be patched in the near future, until then, your best call is to go back to the main menu and try again, or restarting Anki; this often fixes the problem.I'm sorry about it...Creating a new themeThe theme was made with customizability in mind; you can learn more on how to make your own theme in thetheme builder folder's README.Once you've made your own theme, you can submit it as a contribution to make it "official" and share it with others.Contributing and dev documentationThe project was built with contributions and future projects in mind, using expressive names, doc strings on functions/classes/modules and types.You can read more on the project's inner workings in theCONTRIBUTING.md.If you want to help with issues, you can head tothis project's kanban.If you have any questions or find something in the documentation that is not clear, let me know with an issue, I'll (mochitto) will get back to you asap!The reasons behind the projectAnki uses formatted text and html, but makes users pick a very strict way of defining that, while using plain text.
This "helps" some users by shielding them from the possible complexity of formatting the text, but a lot more could be achieved by giving them freedom with Markdown.Markdown formatting also makes space for coding cards, which are pretty awful to make in Anki (even if, thanks toIjgndandGlutanimate, there was at least an ok possibility to make them work).This means that users do not really need tens of note types, but can define the kind of note they actually need while writing them (or by using their own, flexible templates).This also takes away some limitations, such as having to use clozes on only one field of the card.I (mochitto) also really like the idea of Open Source/Free software communicating between different projects, so creating a "bridge" between Obsidian and Anki feels like a great way of pulling together applications that give society a huge value, making them even stronger.Technologies usedLanguagesTypescriptSassPythonBuildingEsbuildEsbuild sass pluginLive serverCore dependenciesMarkdown to HTML parser and compiler:MistuneCode highlighter:PygmentsTestingPytestMethodologyMobile-first approachBEM nomenclatureScalable and Modular Architecture for CSSTest Driven DevelopmentHopes for the futureSome things that I hope will be implemented in the future, either by me (mochitto) or by the community are:A colorblind-friendly themeAn high-contrast themeAny other accessibility improvementSupport for more advanced formatting Markdown optionsAnkiConnectsupport to make imports automaticAn Obsidian addon to run the script/setup the configs from ObsidianSomeone making a video about Markdown2Anki, either to just share it or a guide on how it works and how to install itA comprehensive documentationVersioningThe formatting of the changelog file is based onKeep a Changelogand this project adheres toSemantic Versioning.
You canread the CHANGELOG file here.LicenseThis project uses theGPL3 LICENSE.The project was made possible by lots of free software and is a bridge between free softwares; it couldn't have been made possible withoutPygments,Mistune,Pytest,esbuild,sassand tons more of community efforts.Closing noteI hope this project inspires others to create more open source software, fostering growth and collaboration within our community and society.  - Mochitto, 2023