Transforming Markdown Notes To a Given Target โš—๏ธ

This workflow explains how one could parse a Markdown note to a NoteMate target and utilize the full suite of tools within NoteMate. In this tutorial, we will take a Markdown note to a Franklin.jl target output note. It is an implementation suggestion that one does not have to follow strictly but serves as a starting point in developing one's own workflow.

Requirements ๐Ÿšจ

To follow this tutorial, create a separate project directory โ€“ I will refer to it as projdir going forward โ€“ on your computer, activate Julia, and add the following packages to your project:

pkg> add Dates
pkg> add Markdown
pkg> add NoteMate

Now, we need to copy four files into projdir from the Appendix:

  • Sample Note - copy the content in this file and put it into a file called note.md within projdir.

  • IEEE CSL - copy the content in this file and put it into a file called ieee.csl within projdir.

  • BibTeX References - copy the content in this file and put it into a file called refs.bib within projdir.

  • Processing Script - copy the content in this file and put it into a file called script.jl within projdir.

Once you have copied these files into the projdir, we are ready to go! The following steps will guide you through different pieces of script.jl and how NoteMate works in supporting note processing workflows. At any point, you can run the full script within projdir to test it out.

Pre-Processing of a Markdown Note ๐Ÿšง

To process this note into a NoteMate understandable object, NoteMate provides a series of tools to make some of the rudimentary parsing easier. To get started, we will read this file as a String:

note = read("note.md", String)

The reason why we read this as a String is so that we can do pattern matching to apply various transformations to the raw representation of the note.

Generating Citations ๐Ÿ“š

Let's first extract and replace the citation keys present within this note with their correct inline citations:

# See Steps 1 & 2
citation_keys = find_citation_groups(note) 

# See Steps 3 & 4
inline_citations_dict = create_inline_citations(citation_keys, "refs.bib", "ieee.csl")

# See Step 5
note = replace(note, inline_citations_dict...)

Here is what this code block does:

  1. Find all the citation groups within the String using find_citation_groups().

This returns a vector with all the unique citation groups found within the String.

  1. Store this result in the citation_keys variable.
  2. Define the actual inline reference representation for the found citation keys using create_inline_citations().

This function utilizes refs.bib to map the citation keys found in the String to the correct reference information. Once each key's reference information was found, the ieee.csl file defines how the inline citation should appear within the final note.

  1. Store this mapping within inline_citations_dict
  2. Now, we replace all respective citation groups with their appropriate inline citation.

NOTE: What Will Inline Citations Look Like? As we are using the IEEE CSL format, citation groups that look like this: [@chase1973mind, @simon1973american] will be rendered to look something like this in the document [3, 4].

Next, let's scan the document for any links and see which one are relative links.

NOTE: What Is a Relative Link? These are links that are made within a document that references another note or object within the same directory as the initial document. We want to preserve these relationships as they are transformed so as to not lose this information in an eventual deployment.

To do this, we will use the following code snippet:

# See Steps 1 & 2
markdown_links = find_markdown_links(note, group_links = true)

# See Steps 3 & 4
relative_links_dict = create_relative_links(markdown_links["relative_links"])

# See Steps 5
note = replace(note, relative_links_dict...)

To accomplish this, we will use the following process:

  1. Find all markdown links in a String using find_markdown_links().

By setting the keyword argument, group_links = true, a dictionary of vectors is returned that defines web links (links that link to somewhere on the internet), anchor links (links that jumps to a specific place in a document) or relative links.

  1. Store links within markdown_links.

  2. Using markdown_links, we can use the create_relative_links(), to update or finalize relative links that were found before deployment to a target output.

  3. Store this mapping within relative_links_dict.

  4. Finally, we replace all relative links with their newly updated path.

Processing an OKM Note by Each Component ๐Ÿ› ๏ธ

With pre-processing complete, we can now start ingesting the specifics of the note into OKM components. In particular, we will ingest the following components:

  • Title Block - this is a unique block that begins with the name of the note followed by three required subcomponents:
- **Date** - the date the note was created

- **Summary** - a brief, single sentence summary of what this note is about

- **Keywords** - keywords that can be used to find or associated with the content of this note
  • Bibliography Block - this contains the bibliographic information that is associated with the specific note

  • Notes - where one's notes go on the note subject in whatever format one so chooses

  • References - list of references used in the note

To start, we use Markdown.parse() to generate a parsed representation of the note to turn it into a Julia-understandable Markdown representation:

parsed_note = Markdown.parse(note)

From there, the note can be parsed readily as a Julia Markdown object. NoteMate offers some utility functions to help with this parsing as shown below:

note_headers = get_headers(parsed_note.content)
title_header = filter(x -> typeof(x) <: Header{1}, note_headers)
section_headers = filter(x -> typeof(x) <: Header{2}, note_headers)

sections = get_sections(parsed_note.content, section_headers; name_sections=true)
title_section = get_title_section(parsed_note.content, title_header; name_sections=true)
references_section = create_references(citation_keys, bibtex_path, csl_path)
note_sections = merge!(sections, title_section)
note_sections["References"] = (note_sections["References"][1] |> plain) * "\n" * references_section |> parse |> x -> x.content

title_section = note_sections["Title"]
bibliography_section = note_sections["Bibliography"][2] |> plain
notes_section = note_sections["Notes"][2:end] |> plain
references_section = note_sections["References"] |> plain

title = title_section[1].text[1] |> x -> replace(x, "\"" => "'")
date = title_section[2].content[2] |> strip
summary = title_section[3].content[2] |> strip |> x -> replace(x, "\"" => "'")
keywords = title_section[4].content[2] |> strip

In lieu of explaining all particulars here, here is the general process in how this code block works:

  • get_headers() finds all the Markdown headers in the parsed_note structure.

  • get_sections() will further parse available headers and cut the document apart with all text between each heading isolated as one section.

  • get_title_section(), gets the single section under the first Header{1} and allows it to be parsed into multiple OKM components.

  • create_references() uses the function to generate full references for a note's reference component using the citation_keys variable generated earlier.

  • A combination of various filters are then used to do additional component splitting and parsing to ingest all needed information into the required OKM components.

Then, we can create a NoteMate Note object:

note = Note(title, date, summary, keywords, bibliography_section, references_section, notes_section, basename("notes.md"), "notes.md", "ieee.csl", "refs.bib")

NOTE: Note parsing seems too fragile? If you noticed that parsing this note into each component seemed brittle or too fragile, this is both a strength and a weakness of the OKM. The OKM is flexible enough to allow one to implement the OKM however way they want which gives a lot of flexibility to usage. However, it comes at the cost that any implementation will need to be parsed according to the way it was implemented into a NoteMate `Note`.

Targeting Franklin.jl as an Output Target ๐ŸŽฏ

With the note parsed into an OKM Note object, we can now use NoteMate tools to create a Franklin.jl compliant output. We use create_franklin_note() to created a FranklinNote object that is used by NoteMate and generate_franklin_template() to generate the initial page set-up with necessary Franklin specific syntax mark-up:

franklin_note_raw = create_franklin_note(note)

franklin_note = ""
franklin_note = franklin_note * generate_franklin_template(title=franklin_note_raw.title, slug=franklin_note_raw.slug, tags=franklin_note_raw.tags, description=franklin_note_raw.description, rss_title=franklin_note_raw.rss_title, rss_description=franklin_note_raw.rss_description, rss_pubdate=franklin_note_raw.rss_pubdate)

From here, NoteMate provides a variety of tools that accept a FranklinNote to generate content for a note written using Franklin markup. Here is an example of how this is done:

# Generate summary section
franklin_note = franklin_note * generate_note_summary(franklin_note_raw)

# Generate bibliography section
franklin_note = franklin_note * generate_bibliography(franklin_note_raw)

# Generate a Franklin Table of Contents
franklin_note = franklin_note * generate_table_of_contents()

# Add note content into the Franklin page
franklin_note = franklin_note * franklin_note_raw.notes

# Generate a references output section
franklin_note = franklin_note * generate_references(franklin_note_raw)

# Write the final note to a file
write("franklin_note.md", franklin_note)

Congratulations! You Just Converted Your First Note! ๐Ÿฅณ

Congratulations! This illustrates a potential workflow using NoteMate to go from OKM-compliant Markdown notes to a Franklin note! The final Franklin note then could be directly added to a Franklin-based website deployment and rendered on the internet. This example workflow shows a potential path one could take using NoteMate to ingest an OKM-compliant note and produce an output. Additional functionality could be added to a workflow to, for example, iterate through one's entire note base, add custom sections to a specific output one would want, or swap citation styles on the fly. With the scripting ability enabled by NoteMate to iteratively build notes, the possibilities are numerous.

Appendix ๐Ÿ”

Sample Note

# How Big Is a Chunk?

**Date:** January 07 2023

**Summary:** An interesting foundation for the notion of "chunking" in memory and education research

**Keywords:** #chunk #memory #bit #unit ##bibliography #archive

## Bibliography

H. A. Simon, "How Big Is a Chunk? By combining data from several experiments, a basic human memory unit can be identified and measured.," Science, vol. 183, no. 4124, pp. 482โ€“488, 1974.

## Notes

### Reading Motivation

In reading a piece by Michael Nielsen on using spaced repetition to process mathematics [@nielsenUsingSpacedRepetition2019], he referenced a concept called "chunking".
I hadn't encountered this notion in education research before and thought it sounded interesting. 
So, thus reading the paper.

### What Are Chunks?

Loosely based on [@miller1956magical], chunks are constructs which organize and group together units of information input into memory.
These inputs can be of any form and the basic units could be things like phonemes in words, moves in chess, etc. that can then be recalled at once (a Bible verse, a Sicilian Defense, etc.).
The material stored in a chunk is independent of how many chunks can be generated.

### Benefits of Chunk Generation

The memory span seems to be constrained by a fixed number of chunks (although this number varies wildly in the paper). 
However, we can increase the information stored in memory by increasing the number of units belonging to each chunk.
[@miller1956magical]

As regaled by Simon, an example of chunking in action is this:

> I tried to recall after one reading the following list of words: Lincoln, milky, criminal, differential, address, way, lawyer, calculus, Gettysburg. I had no success whatsoever. I should not have expected success, for the list exceeded my span of six or seven words. Then I rearranged the list a bit, as follows:
> 
> - Lincoln's Gettysburg Address
> - Milky Way 
> - Criminal Lawyer 
> - Differential Calculus
>
> I had no difficulty at all

The variance between chunks and memory can be attributed to larger chunk sizes based on one's expertise with a material. [@chase1973mind, @simon1973american]

## References:

IEEE CSL

<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only">
  <info>
    <title>IEEE</title>
    <id>http://www.zotero.org/styles/ieee</id>
    <link href="http://www.zotero.org/styles/ieee" rel="self"/>
    <!-- <link href="https://ieeeauthorcenter.ieee.org/wp-content/uploads/IEEE-Reference-Guide.pdf" rel="documentation"/> - 2018 guidelines -->
    <link href="http://journals.ieeeauthorcenter.ieee.org/wp-content/uploads/sites/7/IEEE_Reference_Guide.pdf" rel="documentation"/>
    <link href="https://journals.ieeeauthorcenter.ieee.org/your-role-in-article-production/ieee-editorial-style-manual/" rel="documentation"/>
    <author>
      <name>Michael Berkowitz</name>
      <email>mberkowi@gmu.edu</email>
    </author>
    <contributor>
      <name>Julian Onions</name>
      <email>julian.onions@gmail.com</email>
    </contributor>
    <contributor>
      <name>Rintze Zelle</name>
      <uri>http://twitter.com/rintzezelle</uri>
    </contributor>
    <contributor>
      <name>Stephen Frank</name>
      <uri>http://www.zotero.org/sfrank</uri>
    </contributor>
    <contributor>
      <name>Sebastian Karcher</name>
    </contributor>
    <contributor>
      <name>Giuseppe Silano</name>
      <email>g.silano89@gmail.com</email>
      <uri>http://giuseppesilano.net</uri>
    </contributor>
    <contributor>
      <name>Patrick O'Brien</name>
    </contributor>
    <contributor>
      <name>Brenton M. Wiernik</name>
    </contributor>
    <contributor>
      <name>Oliver Couch</name>
      <email>oliver.couch@gmail.com</email>
    </contributor>
    <category citation-format="numeric"/>
    <category field="engineering"/>
    <category field="generic-base"/>
    <summary>IEEE style as per the 2021 guidelines, V 01.29.2021.</summary>
    <updated>2023-04-18T00:52:46+10:00</updated>
    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
  </info>
  <locale xml:lang="en">
    <date form="text">
      <date-part name="month" form="short" suffix=" "/>
      <date-part name="day" form="numeric-leading-zeros" suffix=", "/>
      <date-part name="year"/>
    </date>
    <terms>
      <term name="chapter" form="short">ch.</term>
      <term name="presented at">presented at the</term>
      <term name="available at">available</term>
    </terms>
  </locale>
  <!-- Macros -->
  <macro name="status">
    <choose>
      <if variable="page issue volume" match="none">
        <text variable="status" text-case="capitalize-first" suffix="" font-weight="bold"/>
      </if>
    </choose>
  </macro>
  <macro name="edition">
    <choose>
      <if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
        <choose>
          <if is-numeric="edition">
            <group delimiter=" ">
              <number variable="edition" form="ordinal"/>
              <text term="edition" form="short"/>
            </group>
          </if>
          <else>
            <text variable="edition" text-case="capitalize-first" suffix="."/>
          </else>
        </choose>
      </if>
    </choose>
  </macro>
  <macro name="issued">
    <choose>
      <if type="article-journal report" match="any">
        <date variable="issued">
          <date-part name="month" form="short" suffix=" "/>
          <date-part name="year" form="long"/>
        </date>
      </if>
      <else-if type="bill book chapter graphic legal_case legislation song thesis" match="any">
        <date variable="issued">
          <date-part name="year" form="long"/>
        </date>
      </else-if>
      <else-if type="paper-conference" match="any">
        <date variable="issued">
          <date-part name="month" form="short"/>
          <date-part name="year" prefix=" "/>
        </date>
      </else-if>
      <else-if type="motion_picture" match="any">
        <date variable="issued" form="text" prefix="(" suffix=")"/>
      </else-if>
      <else>
        <date variable="issued" form="text"/>
      </else>
    </choose>
  </macro>
  <macro name="author">
    <names variable="author">
      <name and="text" et-al-min="7" et-al-use-first="1" initialize-with=". "/>
      <label form="short" prefix=", " text-case="capitalize-first"/>
      <et-al font-style="italic"/>
      <substitute>
        <names variable="editor"/>
        <names variable="translator"/>
      </substitute>
    </names>
  </macro>
  <macro name="editor">
    <names variable="editor">
      <name initialize-with=". " delimiter=", " and="text"/>
      <label form="short" prefix=", " text-case="capitalize-first"/>
    </names>
  </macro>
  <macro name="locators">
    <group delimiter=", ">
      <text macro="edition"/>
      <group delimiter=" ">
        <text term="volume" form="short"/>
        <number variable="volume" form="numeric"/>
      </group>
      <group delimiter=" ">
        <number variable="number-of-volumes" form="numeric"/>
        <text term="volume" form="short" plural="true"/>
      </group>
      <group delimiter=" ">
        <text term="issue" form="short"/>
        <number variable="issue" form="numeric"/>
      </group>
    </group>
  </macro>
  <macro name="title">
    <choose>
      <if type="bill book graphic legal_case legislation motion_picture song" match="any">
        <text variable="title" font-style="italic"/>
      </if>
      <else>
        <text variable="title" quotes="true"/>
      </else>
    </choose>
  </macro>
  <macro name="publisher">
    <choose>
      <if type="bill book chapter graphic legal_case legislation motion_picture paper-conference song" match="any">
        <group delimiter=": ">
          <text variable="publisher-place"/>
          <text variable="publisher"/>
        </group>
      </if>
      <else>
        <group delimiter=", ">
          <text variable="publisher"/>
          <text variable="publisher-place"/>
        </group>
      </else>
    </choose>
  </macro>
  <macro name="event">
    <choose>
      <!-- Published Conference Paper -->
      <if type="paper-conference speech" match="any">
        <choose>
          <if variable="container-title" match="any">
            <group delimiter=" ">
              <text term="in"/>
              <text variable="container-title" font-style="italic"/>
            </group>
          </if>
          <!-- Unpublished Conference Paper -->
          <else>
            <group delimiter=" ">
              <text term="presented at"/>
              <text variable="event"/>
            </group>
          </else>
        </choose>
      </if>
    </choose>
  </macro>
  <macro name="access">
    <choose>
      <if type="webpage post post-weblog" match="any">
        <!-- https://url.com/ (accessed Mon. DD, YYYY). -->
        <choose>
          <if variable="URL">
            <group prefix=" " delimiter=" ">
              <text variable="URL"/>
              <group delimiter=" " prefix="(" suffix=").">
                <text term="accessed"/>
                <date variable="accessed" form="text"/>
              </group>
            </group>
          </if>
        </choose>
      </if>
      <else-if match="any" variable="DOI">
        <!-- doi: 10.1000/xyz123. -->
        <text variable="DOI" prefix=" doi: " suffix="."/>
      </else-if>
      <else-if variable="URL">
        <!-- Accessed: Mon. DD, YYYY. [Medium]. Available: https://URL.com/ -->
        <group delimiter=". " prefix=" " suffix=". ">
          <!-- Accessed: Mon. DD, YYYY. -->
          <group delimiter=": ">
            <text term="accessed" text-case="capitalize-first"/>
            <date variable="accessed" form="text"/>
          </group>
          <!-- [Online Video]. -->
          <group prefix="[" suffix="]" delimiter=" ">
            <choose>
              <if variable="medium" match="any">
                <text variable="medium" text-case="capitalize-first"/>
              </if>
              <else>
                <text term="online" text-case="capitalize-first"/>
                <choose>
                  <if type="motion_picture">
                    <text term="video" text-case="capitalize-first"/>
                  </if>
                </choose>
              </else>
            </choose>
          </group>
        </group>
        <!-- Available: https://URL.com/ -->
        <group delimiter=": " prefix=" ">
          <text term="available at" text-case="capitalize-first"/>
          <text variable="URL"/>
        </group>
      </else-if>
    </choose>
  </macro>
  <macro name="page">
    <choose>
      <if type="article-journal" variable="number" match="all">
        <group delimiter=" ">
          <text value="Art."/>
          <text term="issue" form="short"/>
          <text variable="number"/>
        </group>
      </if>
      <else>
        <group delimiter=" ">
          <label variable="page" form="short"/>
          <text variable="page"/>
        </group>
      </else>
    </choose>
  </macro>
  <macro name="citation-locator">
    <group delimiter=" ">
      <choose>
        <if locator="page">
          <label variable="locator" form="short"/>
        </if>
        <else>
          <label variable="locator" form="short" text-case="capitalize-first"/>
        </else>
      </choose>
      <text variable="locator"/>
    </group>
  </macro>
  <macro name="geographic-location">
    <group delimiter=", " suffix=".">
      <choose>
        <if variable="publisher-place">
          <text variable="publisher-place" text-case="title"/>
        </if>
        <else-if variable="event-place">
          <text variable="event-place" text-case="title"/>
        </else-if>
      </choose>
    </group>
  </macro>
  <!-- Series -->
  <macro name="collection">
    <choose>
      <if variable="collection-title" match="any">
        <text term="in" suffix=" "/>
        <group delimiter=", " suffix=". ">
          <text variable="collection-title"/>
          <text variable="collection-number" prefix="no. "/>
          <text variable="volume" prefix="vol. "/>
        </group>
      </if>
    </choose>
  </macro>
  <!-- Citation -->
  <citation collapse="citation-number">
    <sort>
      <key variable="citation-number"/>
    </sort>
    <layout delimiter=", ">
      <group prefix="[" suffix="]" delimiter=", ">
        <text variable="citation-number"/>
        <text macro="citation-locator"/>
      </group>
    </layout>
  </citation>
  <!-- Bibliography -->
  <bibliography entry-spacing="0" second-field-align="flush">
    <layout>
      <!-- Citation Number -->
      <text variable="citation-number" prefix="[" suffix="]"/>
      <!-- Author(s) -->
      <text macro="author" suffix=", "/>
      <!-- Rest of Citation -->
      <choose>
        <!-- Specific Formats -->
        <if type="article-journal">
          <group delimiter=", ">
            <text macro="title"/>
            <text variable="container-title" font-style="italic" form="short"/>
            <text macro="locators"/>
            <text macro="page"/>
            <text macro="issued"/>
            <text macro="status"/>
          </group>
          <choose>
            <if variable="URL DOI" match="none">
              <text value="."/>
            </if>
            <else>
              <text value=","/>
            </else>
          </choose>
          <text macro="access"/>
        </if>
        <else-if type="paper-conference speech" match="any">
          <group delimiter=", " suffix=", ">
            <text macro="title"/>
            <text macro="event"/>
            <text macro="editor"/>
          </group>
          <text macro="collection"/>
          <group delimiter=", " suffix=".">
            <text macro="publisher"/>
            <text macro="issued"/>
            <text macro="page"/>
            <text macro="status"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else-if type="chapter">
          <group delimiter=", " suffix=", ">
            <text macro="title"/>
            <group delimiter=" ">
              <text term="in" suffix=" "/>
              <text variable="container-title" font-style="italic"/>
            </group>
          </group>
          <text macro="editor" suffix=", "/>
          <text macro="edition"/>
          <text macro="collection"/>
          <group delimiter=", " suffix=".">
            <text macro="publisher"/>
            <text macro="issued"/>
            <text macro="page"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else-if type="report">
          <group delimiter=", " suffix=".">
            <text macro="title"/>
            <text macro="publisher"/>
            <group delimiter=" ">
              <text variable="genre"/>
              <text variable="number"/>
            </group>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else-if type="thesis">
          <group delimiter=", " suffix=".">
            <text macro="title"/>
            <text variable="genre"/>
            <text macro="publisher"/>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else-if type="webpage post-weblog post" match="any">
          <group delimiter=", " suffix=".">
            <text macro="title"/>
            <text variable="container-title" font-style="italic"/>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else-if type="patent">
          <group delimiter=", ">
            <text macro="title"/>
            <text variable="number"/>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else-if>
        <!-- Online Video -->
        <else-if type="motion_picture">
          <text macro="geographic-location" suffix=". "/>
          <group delimiter=", " suffix=".">
            <text macro="title"/>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else-if>
        <!-- Generic/Fallback Formats -->
        <else-if type="bill book graphic legal_case legislation report song" match="any">
          <group delimiter=", " suffix=". ">
            <text macro="title"/>
            <text macro="locators"/>
          </group>
          <text macro="collection"/>
          <group delimiter=", " suffix=".">
            <text macro="publisher"/>
            <text macro="issued"/>
            <text macro="page"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else-if type="article-magazine article-newspaper broadcast interview manuscript map patent personal_communication song speech thesis webpage" match="any">
          <group delimiter=", " suffix=".">
            <text macro="title"/>
            <text variable="container-title" font-style="italic"/>
            <text macro="locators"/>
            <text macro="publisher"/>
            <text macro="page"/>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else-if>
        <else>
          <group delimiter=", " suffix=". ">
            <text macro="title"/>
            <text variable="container-title" font-style="italic"/>
            <text macro="locators"/>
          </group>
          <text macro="collection"/>
          <group delimiter=", " suffix=".">
            <text macro="publisher"/>
            <text macro="page"/>
            <text macro="issued"/>
          </group>
          <text macro="access"/>
        </else>
      </choose>
    </layout>
  </bibliography>
</style>

BibTeX References

@online{nielsenUsingSpacedRepetition2019,
  title = {Using Spaced Repetition Systems to See through a Piece of Mathematics},
  author = {Nielsen, Michael},
  date = {2019},
  url = {http://cognitivemedium.com/srs-mathematics}
}

@article{miller1956magical,
  title = {The Magical Number Seven, plus or Minus Two: {{Some}} Limits on Our Capacity for Processing Information.},
  author = {Miller, George A},
  date = {1956},
  journaltitle = {Psychological review},
  shortjournal = {Psychol. Rev.},
  volume = {63},
  number = {2},
  pages = {81},
  publisher = {{American Psychological Association}}
}

@incollection{chase1973mind,
  title = {The Mind's Eye in Chess},
  booktitle = {Visual Information Processing},
  author = {Chase, William G and Simon, Herbert A},
  date = {1973},
  pages = {215--281},
  publisher = {{Elsevier}}
}

@article{simon1973american,
  title = {American Scientist},
  author = {Simon, Herbert A and Chase, William G},
  date = {1973},
  journaltitle = {Scientist (Philadelphia, Pa.)},
  shortjournal = {Scientist},
  volume = {61},
  number = {4},
  pages = {394--403}
}

Full Script

Here was the full script that was developed in the course of this tutorial:

using Dates
using NoteMate

import Markdown:
    Header,
    plain

note = read("note.md", String)

citation_keys = find_citation_groups(note) 
inline_citations_dict = create_inline_citations(citation_keys, "refs.bib", "ieee.csl")
note = replace(note, inline_citations_dict...)

markdown_links = find_markdown_links(note, group_links = true)
relative_links_dict = create_relative_links(markdown_links["relative_links"])
note = replace(note, relative_links_dict...)

parsed_note = Markdown.parse(note)

note_headers = get_headers(parsed_note.content)
title_header = filter(x -> typeof(x) <: Header{1}, note_headers)
section_headers = filter(x -> typeof(x) <: Header{2}, note_headers)

sections = get_sections(parsed_note.content, section_headers; name_sections=true)
title_section = get_title_section(parsed_note.content, title_header; name_sections=true)
references_section = create_references(citation_keys, "refs.bib", "ieee.csl")
note_sections = merge!(sections, title_section)
note_sections["References"] = (note_sections["References"][1] |> plain) * "\n" * references_section |> Markdown.parse |> x -> x.content

title_section = note_sections["Title"]
bibliography_section = note_sections["Bibliography"][2] |> plain
notes_section = note_sections["Notes"][2:end] |> plain
references_section = note_sections["References"] |> plain

title = title_section[1].text[1] |> x -> replace(x, "\"" => "'")
date = title_section[2].content[2] |> strip
summary = title_section[3].content[2] |> strip |> x -> replace(x, "\"" => "'")
keywords = title_section[4].content[2] |> strip

note = Note(title, date, summary, keywords, bibliography_section, references_section, notes_section, basename("notes.md"), "notes.md", "ieee.csl", "refs.bib")

franklin_note_raw = create_franklin_note(note)

franklin_note = ""
franklin_note = franklin_note * generate_franklin_template(title=franklin_note_raw.title, slug=franklin_note_raw.slug, tags=franklin_note_raw.tags, description=franklin_note_raw.description, rss_title=franklin_note_raw.rss_title, rss_description=franklin_note_raw.rss_description, rss_pubdate=franklin_note_raw.rss_pubdate)

franklin_note = franklin_note * generate_note_summary(franklin_note_raw)
franklin_note = franklin_note * generate_bibliography(franklin_note_raw)
franklin_note = franklin_note * generate_table_of_contents()
franklin_note = franklin_note * franklin_note_raw.notes
franklin_note = franklin_note * generate_references(franklin_note_raw)

write("franklin_note.md", franklin_note)