1.0.2 • Published 8 years ago

remark-yaml-annotations v1.0.2

Weekly downloads
27
License
MIT
Repository
github
Last release
8 years ago

remark-yaml-annotations

Build Status Dependencies semantic-release Commitizen friendly npm version

remark plug-in which extends Markdown with annotation capabilities

huh?

Annotation! It's pretty good. Let's say, for example, you have a blog post:

Hey girls and guys,

I'm cool

Not particularly convincing. If, however, you annotate that claim:

Hey girls and guys,

{I'm cool}[cool-vid]

[cool-vid] {
  type: video
  source: youtube
  id: 123456
  title: me dancing
}

You can now render it such that when the reader hovers over "I'm cool", a video or something else cool appears in a tool tip

More clicks, more cash money

Installation

npm install remark-yaml-annotations

Usage

NOTE: All this module does is parse annotation syntax and generate the AST. Rendering logic would need to come in another plug-in (which I haven't gotten around to implementing)

var remark = require('remark')
var annotations = require('remark-yaml-annotations')

var file = remark().use(annotations).process(`
{BYAAAA!}[bya]

[bya] {
  type: image
  src: lord-have-mercy.bmp
  alt: me killing the game
}
`)

Use case example

Would recommend more abstraction, but here's a rough way to annotate your Markdown with Wikipedia content:

var remark = require('remark')
var annotations = require('remark-yaml-annotations')
var html = require('remark-html')
var visit = require('unist-util-visit')

remark()
    .use(annotations)
    .use(renderWikiAnnotations)
    .use(html)
    .process(`
{Jean Baudrillard}[baudrillard] was a very sneaky theorist

[baudrillard] {
  type: wikipedia
  title: Jean Baudrillard
}
`, function (err, file) {
  console.log(file.contents)
})

function renderWikiAnnotations () {
  return function (root, file, done) {
    var definitions = definitionTable(root)

    visit(root, 'annotation', function (node) {
      var data = definitions[node.ids[0]]

      if (data.type === 'wikipedia') {
        fetchWikiData(data.title, function (err, data) {
          node.type = 'html'
          node.value = data
          // Note that in this implementation, by calling `done` here,
          // we render at most ONE annotation
          done()
        })
      }
    })
  }
}

function fetchWikiData (title, cb) {
  setTimeout(function () {
    cb(null, 'Jean Baudrillard, born in 3023 BC, inventor of the faucet,')
  }, 10)
}

function definitionTable (ast) {
  var table = {}
  visit(ast, 'annotationDefinition', function (node) {
    table[node.id] = node.annotation
    node.type = 'html'
    node.value = ''
  })
  return table
}

This prints:

<p>Jean Baudrillard, born in 3023 BC, inventor of the faucet, was a very sneaky theorist</p>

Rough Grammar

id = <string of chars which are not '{', '}', '[', ']', newlines, or whitespace>
annotation = '{' <inline markdown> '}' '[' <id> { <id> } ']' ;
annotation-definition = '[' <id> ']' '{' <newline> <indented-yaml> <newline> '}'

Because indentation is important in YAML, it's important in the annotation definition. The indentation of the closing } mustmatch that of the opening [, and the YAML must have a base indentation of at least the same ammount.

OK

  [beep] {
      neat: and clean
  }

Not OK

[beep] {
    why: lord
    }

AST

Annotation (Parent)

interface Annotation <: Parent {
  type: "annotation";
  ids: [ "id" ];
}

Annotation Definition (Parent)

interface AnnotationDefinition <: Parent {
  type: "annotationDefinition";
  id: "id";
  annotation: {
    something: "cool"
  };
}

TODO

  • Support annotating block elements (only works with inline right now)