2022-08-26

Remark Presentation to Anki Deck

I modified the main script in this repository to create a set of Anki flashcards out of a Remark presentation.

A new card starts with a three dashed-line ---, and -- separates the front and back of the card. Slide notes (??? separator) can also be extracted with the -n option.

When executed from the command line, the standard output from this script can be redirected to create an HTML file (filename.md is the remark presentation):

   $ markdown_to_anki filename.md > filename.html

This HTML file can then be imported into the Anki desktop application as shown in the video below.

A deck can be created with VIM and previewed inside the browser before being included to the Anki database, an alternative that I find preferable compared to Anki's built-in editor.

The video below shows the same slides rendered inside the browser and with the Anki desktop app.

Here's the modified script, note that it also sets a predefined style for code blocks.

    #!/usr/bin/env node
    // filename: markdown_to_anki
    function pipe(initial, ...fns) {
      return fns.reduce((val, f) => f(val), initial)
    }

    function showHelp() {
      console.error(`
    markdown-to-anki <filename>
      `)
    }
    function replaceUndefinied(item) {
       var str =  JSON.stringify(item, function (key, value) {return (value === undefined) ? "" : value});
       return JSON.parse(str);
    }

    const fs = require('fs')
    const marked = require('marked')
    const argv = process.argv.slice(2)

    if (argv[0] === '--help' || argv[0] === 'help' || argv[0] === '-h') {
      showHelp()
      process.exit(1)
    }

    if (argv[0] == '-n')
    {
        var filename = argv[1]
    }
    else 
    {
        var filename = argv[0]
    }
    if (typeof filename === 'undefined') {
          console.error('Please pass a filename')
        showHelp()
         process.exit(1)
    }

    if (! fs.existsSync(filename)) {
      console.error(`File not found, "${filename}"!`)
      process.exit(1)
    }

    const fileContents = fs.readFileSync(filename)
      .toString()
      .replace(/\t/g, ' ')


    if (argv[0] === "-n"){
    const cards = pipe(
      fileContents,
      contents => contents.split('\n---\n'),
      
      cards => cards.map(card => card.split('\n--\n')),
      cards => cards.map( card => card.map(card => card.split("\n???\n"))),

      cards => cards.map(card => card.map(card => card.map(face => marked(face).replace(/\n/g, '<br>').replace('<pre>','<pre style="color: blue;text-align: left;>"')))),

      cards => cards.map(([front, back]) => front[0] + '\t' + back[0] +"\t"+replaceUndefinied(front[1])+" "+replaceUndefinied(back[1])),
      cards => cards.join('\n'),
       )

    console.log(cards)
    }
    else
    {
      
    const cards = pipe(
      fileContents,
      contents => contents.split('\n---\n'),
      
      cards => cards.map(card => card.split('\n--\n')),

      cards => cards.map(card => card.map(face => marked(face).replace(/\n/g, '<br>').replace('<pre>','<pre style="color: blue;text-align: left;>"'))),
      cards => cards.map(([front, back]) => front + '\t' + back),

      cards => cards.join('\n'),
    )

    console.log(cards)
    }