-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add AnkiConnect plugin support #29
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,7 @@ PyPi - https://pypi.org/project/markdown2anki | |
- **Support for clozes** including those in code blocks. | ||
- **Support for images** with 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. | ||
- **Automatic upload of cards to Anki**: the program uses the [AnkiConnect plugin] to upload the cards to Anki automatically. | ||
- **Accessible config file** that can self-heal (using [Type-Config](https://pypi.org/project/type-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. | ||
|
@@ -65,6 +66,8 @@ PyPi - https://pypi.org/project/markdown2anki | |
- **Mobile first responsive CSS**: to ensure it's fully responsive on all devices. | ||
- **High-level dev documentation** to make it easier for contributions and maintenance. | ||
|
||
[AnkiConnect plugin]: https://foosoft.net/projects/anki-connect/ | ||
|
||
## Images | ||
|
||
### CLI | ||
|
@@ -130,6 +133,13 @@ There will also be a `markdown2anki.apkg` file which contains the anki note type | |
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 `.apkg` files here: https://docs.ankiweb.net/exporting.html#deck-apkg | ||
|
||
### Installing the AnkiConnect plugin | ||
|
||
If you want the `md2anki` to automatically uploaded the generated cards to Anki, you will need to install the [AnkiConnect plugin](https://ankiweb.net/shared/info/2055492159). | ||
As when installing any other Anki plugin, navigate to the `Tools>Add-ons` menu, click on the `Get Add-ons` button, and paste the code `2055492159` in the `Code` field and click `OK`. | ||
|
||
If you don't want to install the AnkiConnect plugin, you can use the [legacy CSV file] output, which you can then import manually. | ||
|
||
### Using fill the blanks | ||
|
||
If you would like to have "type-in" clozes, you can use this addon: [fill the blanks addon](https://ankiweb.net/shared/info/1933645497). | ||
|
@@ -197,7 +207,7 @@ is the same as | |
|
||
#### Example | ||
Here are two example cards to illustrate the formatting requirements: | ||
```markdown | ||
`````markdown | ||
## - [Question] | ||
# A great addition to humanity | ||
What is the **name** of this funny cat? | ||
|
@@ -219,34 +229,55 @@ my_list = [3,5,2] | |
sorted_list = {{C1::sorted}}(my_list, {{C1::True}}) | ||
# In place | ||
my_list.{{C1::sort}}(True) | ||
``` | ||
|
||
``` | ||
````` | ||
|
||
The result: | ||
 | ||
 | ||
(This is using the [fill the blanks addon](https://ankiweb.net/shared/info/1933645497)) | ||
 | ||
|
||
### Importing your cards | ||
Once you have processed your cards, they will be divided in cards with clozes and cards without clozes. | ||
Those will become two `.csv` files: `basic_anki_cards.csv` and `clozed_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 `.csv` file, you have to let anki know that the separator used is `Comma`, select the right `note type` and 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. | ||
### Frontmatter and possible options | ||
|
||
Markdown2Anki uses [Frontmatter] metadata to add file specific metadata to your cards. | ||
Frontmatter is essentially a YAML block that is enclosed by three dashes `---`. | ||
It must be placed at the beginning of your markdown file, before the first card. | ||
Frontmatter contains mandatory and optional metadata fields. | ||
|
||
Here is a basic structure of a Frontmatter block with mandatory fields: | ||
```yaml | ||
--- | ||
deck_name: "My deck" | ||
note_type_basic: "Markdown2Anki - Basic" | ||
note_type_cloze: "Markdown2Anki - Cloze" | ||
--- | ||
``` | ||
|
||
Below is a list of the available options that can be set in the frontmatter block: | ||
|
||
Mandatory fields: | ||
- `deck_name` - The name of the deck where the cards will be imported. | ||
- `note_type_basic` - The name of the note type for basic cards. | ||
- `note_type_clode` - The name of the note type for cards with clozes. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo |
||
|
||
Optional fields: | ||
- `tags` - A list of tags to be added to the cards. | ||
- `no_tabs: True` - Disables tabs in generated cards. If set then: | ||
- `L`, `R`, `-`, `+` tab flags are ignored, only `F` and `B` matter. | ||
- Tab labels are ignored. | ||
|
||
[Frontmatter]: https://dev.to/dailydevtips1/what-exactly-is-frontmatter-123g | ||
|
||
### Importing your card via the AnkiConnect pluging | ||
|
||
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): | ||
 | ||
After the cards are generated they are automatically imported into Anki via the AnkiConnect plugin. | ||
Besides having the plugin installed in you Anki and having Anki open in the background, you don't need to do anything else. | ||
|
||
You can find more information on importing to Anki here: https://docs.ankiweb.net/importing.html | ||
If you don't want to use AnkiConnect plugin you can use the [legacy CSV file] output, which you can then import manually. | ||
|
||
### Importing your images | ||
You can import images automatically if you add the path to your [Anki media folder](https://docs.ankiweb.net/files.html#file-locations) in 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. | ||
[legacy CSV file]: ./docs/legacy_importing_cards_with_csv.md | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can turn this into a markdown link |
||
|
||
Hopefully, in the near future, the importing part will be made automatic by the addition of `AnkiConnect` support. | ||
|
||
### Errors and Bad cards | ||
When there are errors in formatting, the app will let you know what went wrong and create a `Bad_cards.md` file in your program folder. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just great :) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
## Importing your cards via CSV - Legacy feature | ||
|
||
<!-- prettier-ignore --> | ||
> ![NOTE] | ||
> This feature is considered legacy. Currently, the recommended way to import | ||
> cards is via AnkiConnect plugin. To use this feature, you need to set `"use legacy CVS output?"` | ||
> option in .ini config file to `True`. | ||
|
||
### Importing your cards | ||
|
||
Once you have processed your cards, they will be divided in cards with clozes | ||
and cards without clozes. Those will become two `.csv` files: | ||
`basic_anki_cards.csv` and `clozed_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 `.csv` file, you have to let anki know that the | ||
separator used is `Comma`, select the right `note type` and 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.html | ||
|
||
### Importing your images | ||
|
||
You can import images automatically if you add the path to your | ||
[Anki media folder](https://docs.ankiweb.net/files.html#file-locations) in 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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Anki code</title> | ||
<link rel="stylesheet" href="dist/style/main.css" /> | ||
</head> | ||
<body style="overflow: hidden"> | ||
<!-- Needed to avoid scrollbars on absolute elements--> | ||
<main class="l-row-flex l-viewport"> | ||
<div class="body"> | ||
<div class="body__content"> | ||
<h1>This is a test to understand how to style the cards</h1> | ||
<p>This is some text, my plans are:</p> | ||
<ul> | ||
<li>Get this code to look as expected</li> | ||
<li>Continue</li> | ||
</ul> | ||
<section class="highlight highlight--linenos"> | ||
<span class="highlight__language">JavaScript</span> | ||
<div class="highlight__code highlight--linenos"> | ||
<pre><span></span><span class='highlight__line'><span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cloze">workspace</span><span class="p">,</span><span class="w"> </span><span class="nx">ConfigurationChangeEvent</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"vscode"</span><span class="p">;</span><span class="w"></span></span><span class='highlight__line'><span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cloze">getThemePaths</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./helpers"</span><span class="p">;</span><span class="w"></span></span><span class='highlight__line'><span class="k">import</span><span class="w"> </span><span class="nx">utils</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">UpdateTrigger</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./utils"</span><span class="p">;</span><span class="w"></span></span><span class='highlight__line'></span><span class='highlight__line'><span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">activate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="p">{</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">paths</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getThemePaths</span><span class="p">();</span><span class="w"></span></span><span class='highlight__line'></span><span class='highlight__line'><span class="w"> </span><span class="c1">// regenerate on a fresh install if non-default config is set</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">utils</span><span class="p">.</span><span class="nx">isFreshInstall</span><span class="p">()</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="nx">utils</span><span class="p">.</span><span class="nx">isDefaultConfig</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">utils</span><span class="p">.</span><span class="nx">updateThemes</span><span class="p">(</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">utils</span><span class="p">.</span><span class="nx">getConfiguration</span><span class="p">(),</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">paths</span><span class="p">,</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">UpdateTrigger</span><span class="p">.</span><span class="nx">FRESH_INSTALL</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="p">);</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="p">}</span><span class="w"></span></span><span class='highlight__line'></span><span class='highlight__line'><span class="w"> </span><span class="c1">// regenerate the theme files when the config changes</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">workspace</span><span class="p">.</span><span class="nx">onDidChangeConfiguration</span><span class="p">((</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="nx">ConfigurationChangeEvent</span><span class="p">)</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="p">{</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">affectsConfiguration</span><span class="p">(</span><span class="s2">"catppuccin"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">utils</span><span class="p">.</span><span class="nx">updateThemes</span><span class="p">(</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">utils</span><span class="p">.</span><span class="nx">getConfiguration</span><span class="p">(),</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">paths</span><span class="p">,</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="nx">UpdateTrigger</span><span class="p">.</span><span class="nx">CONFIG_CHANGE</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="p">);</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="p">}</span><span class="w"></span></span><span class='highlight__line'><span class="w"> </span><span class="p">});</span><span class="w"></span></span><span class='highlight__line'><span class="p">};</span><span class="w"></span></span><span class='highlight__line'></span><span class='highlight__line'><span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">deactivate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="p">{};</span><span class="w"></span></span></pre> | ||
</div> | ||
</section> | ||
</div> | ||
</div> | ||
</main> | ||
<script src="dist/main.js"></script> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing notes on the other frontmatter options and ankiconnect support