Skip to content
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

Regex: Flashcards from native callout blocks (admonitions) #332

Open
GBergatto opened this issue Apr 25, 2022 · 21 comments
Open

Regex: Flashcards from native callout blocks (admonitions) #332

GBergatto opened this issue Apr 25, 2022 · 21 comments

Comments

@GBergatto
Copy link

This regex creates a flashcards from callout blocks, that are now native to Obsidian as of v0.14.0.

Regex line: (?:\> \[!anki\]-) ([^\n]+)\n(.+(?:\n(?:^.{1,3}$|^.{4}(?<!<!--).*))*)

To make it more specific, the regex will only match a callout block that start with > [!anki]-.
This allows you to keep using all defaults callout blocks without any issues.

Example

> [!anki]- First flashcard
> This is the body of the callout
> $Math$ and `inline code` both work.  
> $$\dfrac{\sum _{i}m_{i}\vec{a}_{i}}{m}$$

> [!check]- Any other callout block will be left untouched
> This will NOT generate a flashcard

> [!anki]- Second flashcard
Lines of the body don't have to start with a > just like for Obsidian
These lines will be displayed by Obsidian as part of the callout block's body and will be part of the flashcard.

This is not part of the flashcard as it's separated by a blank line. 

image

image

Why this regex?

I see this regex as a replacement for the Markdown table style. The goal is the same: it looks nice when rendered in the Preview view of Obsidian.

The benefits over the markdown table are:

  • callout blocks can be collapsed
  • more selective: only one type of callout is matched while all other are left untouched
  • more customizable: it's possible to create a CSS snippet to style this custom block any way you like. (See image below)

image

@kueykuang
Copy link

Hey! I love your work, it looks pleasant and integrated. Is it possible to add a whitespace in-between the body?

Screen Shot 2022-05-13 at 19 00 46

(I want to add a whitespace between _classical conditioning_ and _operant conditioning_ to make it easier to read.)

@GBergatto
Copy link
Author

I'm glad you like it.
"Is it possible to add a whitespace in-between the body?"
Yes, it is. According to the Obsidian syntax, you can add a blank line inside the body of the callout block as long as you start it with a >. See the example below:

> [!anki]- Title of the flashcard
> **Classical conditioning**
> Some text...
> 
> **Operant conditioning**
> Some other text...

image

Here's how the flashcard looks like in Anki
image

@kueykuang
Copy link

That was very helpful. Thank you.

@asharokhin
Copy link

Thank you, GBergatto, great work!
For anyone, who might be interested: this regex works not only for Basic card type, but also at least for Cloze and Basic (type in answer) types. You just have to change in the regex line how the callout block starts, for example > [!anki-cloze]- for Cloze card type and > [!anki-typein]- for type in cards.

@marcsolanadal
Copy link

marcsolanadal commented Jun 16, 2022

I wonder if someone has implemented this using the obsidian-admonition plugin. In my opinion it would make cards much easier to type and the markdown would be cleaner.

@huongnguyenduc
Copy link

huongnguyenduc commented Jun 29, 2022

Awesome regex!!! Thanks for save my time to find solution to integrate obsidian callout and anki flashcard :3

@SubZeroX
Copy link

SubZeroX commented Jul 1, 2022

Thanks for this @GBergatto. Images can be used?

@GBergatto
Copy link
Author

Thanks for this @GBergatto. Images can be used?

Yes, you can add images too. You simply need to embed them into the body of the callout block

> [!anki]- Flashcard with image
> ![](link-to-image)

@SubZeroX
Copy link

Awesome, it does work really nice. Only thing I noticed is that the answer is been added as a blockquote. Is there anyway to correct that?
image

@GBergatto
Copy link
Author

GBergatto commented Jul 18, 2022

Awesome, it does work really nice. Only thing I noticed is that the answer is been added as a blockquote. Is there anyway to correct that?

@SubZeroX
I'd never noticed that and I don't know how that could be fixed. As you can see from the picture below, when I open a card from the Anki editing view, it doesn't show any HTML tags like in your screenshot. All I can see is that the text inside the "Back" field has an unexpected indentation which I guess is caused by the "blockquote" tag.

image

Anyway, I don't think that it changes the way the content is displayed inside Anki, or does it?

@SubZeroX
Copy link

Awesome, it does work really nice. Only thing I noticed is that the answer is been added as a blockquote. Is there anyway to correct that?

@SubZeroX I'd never noticed that and I don't know how that could be fixed. As you can see from the picture below, when I open a card from the Anki editing view, it doesn't show any HTML tags like in your screenshot. All I can see is that the text inside the "Back" field has an unexpected indentation which I guess is caused by the "blockquote" tag.

image

Anyway, I don't think that it changes the way the content is displayed inside Anki, or does it?

Yep, it don't changes the behavior at all. In order to show the html in Anki you need to type the combo "CTRL+SHIFT+X".

Much appreciated for your answers

@rodrigolanes
Copy link

Has anyone tried to get the callout information when it has a description or not? I tried but was not successful.

Example 1 - Many line description

Callout

[!anki-cloze]- Question with {c1:two or more} lines of description.
Explanation - Line 1
Explanation - Line 2
Explanation - Line 3

Anki Fields
text: Question with {c1:two or more} lines of description.
extra: Explanation - Line 1
Explanation - Line 2
Explanation - Line 3

Example 2 - One line description

Callout

[!anki-cloze]- Question with {c1:only} one line of description
Explanation - Line 1

Anki Fields
text: Question with {c1:only} one line of description
extra: Explanation - Line 1

Example 3 - No description

Callout

[!anki-cloze]- {c1:Only} the question.

Anki Fields
text: {c1:Only} the question.
extra:

@Ganomee
Copy link

Ganomee commented Sep 24, 2022

Awesome, it does work really nice. Only thing I noticed is that the answer is been added as a blockquote. Is there anyway to correct that? image

I had the same problem as you do. Unfortunately, it is not easily fixable via regex, but what you can do is to edit the processing step to handle these types of notes. To do that you need to edit your main.js file of this plugin - replace the format function with the following:

/**
     * Removes a single layer of indentation from notes that are fully indented e.g. in callouts
     * @param {string} note_text 
     * @returns string
     */
     formatCallouts(note_text){
      let split_string = note_text.split('\n')
      if(!split_string.every(line => line.charAt(0) =='>'))
      {
            return note_text
      }
      split_string = split_string.map(line => line.substring(1))
      note_text = split_string.join('\n')
      return note_text


    }
    format(note_text, cloze, highlights_to_cloze) {
        note_text = this.obsidian_to_anki_math(note_text);
        //Extract the parts that are anki math
        let math_matches;
        let inline_code_matches;
        let display_code_matches;
        const add_highlight_css = note_text.match(OBS_DISPLAY_CODE_REGEXP) ? true : false;
        [note_text, math_matches] = this.censor(note_text, ANKI_MATH_REGEXP, MATH_REPLACE);
        [note_text, display_code_matches] = this.censor(note_text, OBS_DISPLAY_CODE_REGEXP, DISPLAY_CODE_REPLACE);
        [note_text, inline_code_matches] = this.censor(note_text, OBS_CODE_REGEXP, INLINE_CODE_REPLACE);
        if (cloze) {
            if (highlights_to_cloze) {
                note_text = note_text.replace(HIGHLIGHT_REGEXP, "{$1}");
            }
            note_text = this.curly_to_cloze(note_text);
        }
        note_text = this.getAndFormatMedias(note_text);
        note_text = this.formatLinks(note_text);
        // Special Processing for Full Codeblock Notes (e.g. Callouts)
        note_text = this.formatCallouts(note_text) 
        //Special for formatting highlights now, but want to avoid any == in code
        note_text = note_text.replace(HIGHLIGHT_REGEXP, String.raw `<mark>$1</mark>`);
        note_text = this.decensor(note_text, DISPLAY_CODE_REPLACE, display_code_matches, false);
        note_text = this.decensor(note_text, INLINE_CODE_REPLACE, inline_code_matches, false);
        note_text = converter.makeHtml(note_text);
        note_text = this.decensor(note_text, MATH_REPLACE, math_matches, true).trim();
        // Remove unnecessary paragraph tag
        if (note_text.startsWith(PARA_OPEN) && note_text.endsWith(PARA_CLOSE)) {
            note_text = note_text.slice(PARA_OPEN.length, -1 * PARA_CLOSE.length);
        }
        if (add_highlight_css) {
            note_text = '<link href="' + CODE_CSS_URL + '" rel="stylesheet">' + note_text;
        }
        return note_text;
    }

@Davidb-2107
Copy link

Hi! I've started using your regex thaht mak my vaul much cleaner! Thanks for the job!!!
However is there a way to add a link to where the callout block is saved in my obsidian vault ?

@GBergatto
Copy link
Author

Hi! I've started using your regex thaht mak my vaul much cleaner! Thanks for the job!!! However is there a way to add a link to where the callout block is saved in my obsidian vault ?

@Davidb-2107 Yes, from the plugin settings
image

All you need to do is choose which field should contain the "file link" and the plugin will take care of the rest

@NeuroNoob
Copy link

Awesome, it does work really nice. Only thing I noticed is that the answer is been added as a blockquote. Is there anyway to correct that? image

I had the same problem as you do. Unfortunately, it is not easily fixable via regex, but what you can do is to edit the processing step to handle these types of notes. To do that you need to edit your main.js file of this plugin - replace the format function with the following:

/**
     * Removes a single layer of indentation from notes that are fully indented e.g. in callouts
     * @param {string} note_text 
     * @returns string
     */
     formatCallouts(note_text){
      let split_string = note_text.split('\n')
      if(!split_string.every(line => line.charAt(0) =='>'))
      {
            return note_text
      }
      split_string = split_string.map(line => line.substring(1))
      note_text = split_string.join('\n')
      return note_text


    }
    format(note_text, cloze, highlights_to_cloze) {
        note_text = this.obsidian_to_anki_math(note_text);
        //Extract the parts that are anki math
        let math_matches;
        let inline_code_matches;
        let display_code_matches;
        const add_highlight_css = note_text.match(OBS_DISPLAY_CODE_REGEXP) ? true : false;
        [note_text, math_matches] = this.censor(note_text, ANKI_MATH_REGEXP, MATH_REPLACE);
        [note_text, display_code_matches] = this.censor(note_text, OBS_DISPLAY_CODE_REGEXP, DISPLAY_CODE_REPLACE);
        [note_text, inline_code_matches] = this.censor(note_text, OBS_CODE_REGEXP, INLINE_CODE_REPLACE);
        if (cloze) {
            if (highlights_to_cloze) {
                note_text = note_text.replace(HIGHLIGHT_REGEXP, "{$1}");
            }
            note_text = this.curly_to_cloze(note_text);
        }
        note_text = this.getAndFormatMedias(note_text);
        note_text = this.formatLinks(note_text);
        // Special Processing for Full Codeblock Notes (e.g. Callouts)
        note_text = this.formatCallouts(note_text) 
        //Special for formatting highlights now, but want to avoid any == in code
        note_text = note_text.replace(HIGHLIGHT_REGEXP, String.raw `<mark>$1</mark>`);
        note_text = this.decensor(note_text, DISPLAY_CODE_REPLACE, display_code_matches, false);
        note_text = this.decensor(note_text, INLINE_CODE_REPLACE, inline_code_matches, false);
        note_text = converter.makeHtml(note_text);
        note_text = this.decensor(note_text, MATH_REPLACE, math_matches, true).trim();
        // Remove unnecessary paragraph tag
        if (note_text.startsWith(PARA_OPEN) && note_text.endsWith(PARA_CLOSE)) {
            note_text = note_text.slice(PARA_OPEN.length, -1 * PARA_CLOSE.length);
        }
        if (add_highlight_css) {
            note_text = '<link href="' + CODE_CSS_URL + '" rel="stylesheet">' + note_text;
        }
        return note_text;
    }

Hello! I'm unsure where exactly in main.js I should paste this? As the name implies I'm new to tinkering around with code! :P

@Ganomee
Copy link

Ganomee commented Jan 27, 2023

Hey, no worries. In the main.js there should already be a function called format(...). You just have to replace the existing format function with the code snippet provided. Essentially, this just modifies the format function and adds the format callouts function. Does that help?

@BMuana
Copy link

BMuana commented Apr 3, 2023

Great expression. It is possible to add one more file, like a source, notes or whatever. Thanks

Captura_de_pantalla_2023-04-03_a_las_12_25_51

@thinley99
Copy link

I absolute love this Regex. It's even better than the common ones!

I have been wondering: Is there a way to manually tag cards with this regex? If I append a "Tags: [Tag]", it doesn't register and only shows up as a text in the answer field.

@UlliDa
Copy link

UlliDa commented Feb 16, 2024

Hi GBergatto,

thanks for the great work - i am using it a lot for my studies. Do you have a idea how to modify the regex for nested callouts or multiple callouts in one admonition? For example like this:

`
```ad-note

[!anki]- First flashcard
This is the body of the callout
$Math$ and inline code both work.
$$\dfrac{\sum {i}m{i}\vec{a}_{i}}{m}$$

[!check]- Any other callout block will be left untouched
This will NOT generate a flashcard

[!anki]- Second flashcard
Lines of the body don't have to start with a > just like for Obsidian
These lines will be displayed by Obsidian as part of the callout block's body and will be part of the flashcard.

This is not part of the flashcard as it's separated by a blank line.
```
`
I tired to manage by myself but not very succesful..

@GBergatto
Copy link
Author

@daelen-j I'm not sure what you mean. FYI I have stopped using this plugin and this regex, so I'm not sure I will be able to test any changes to the original regex I posted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests