unified

Project: syntax-tree/mdast-util-directive

Package: mdast-util-directive@2.1.0

  1. Dependents: 3
  2. mdast extension to parse and serialize generic directives (:cite[smith04])
  1. util 143
  2. utility 139
  3. markdown 131
  4. unist 127
  5. mdast 85
  6. mdast-util 30
  7. markup 18
  8. extension 9
  9. container 4
  10. generic 3
  11. directive 3

mdast-util-directive

Build Coverage Downloads Size Sponsors Backers Chat

Extension for mdast-util-from-markdown and/or mdast-util-to-markdown to support the generic directives proposal (:cite[smith04], ::youtube[Video of a cat in a box]{v=01ab2cd3efg}, and such) in mdast. When parsing (from-markdown), must be combined with micromark-extension-directive.

See micromark-extension-directive for how the syntax works. This utility handles parsing and serializing. Traverse the tree to change them to whatever you please.

When to use this

Use this if you’re dealing with the AST manually. It might be better to use remark-directive with remark, which includes this but provides a nicer interface and makes it easier to combine with hundreds of plugins.

Install

This package is ESM only: Node 12+ is needed to use it and it must be imported instead of required.

npm:

npm install mdast-util-directive

Use

Say our module, example.js, looks as follows:

import {fromMarkdown} from 'mdast-util-from-markdown'
import {toMarkdown} from 'mdast-util-to-markdown'
import {directive} from 'micromark-extension-directive'
import {directiveFromMarkdown, directiveToMarkdown} from 'mdast-util-directive'

const doc = 'A lovely language know as :abbr[HTML]{title="HyperText Markup Language"}.'

const tree = fromMarkdown(doc, {
  extensions: [directive()],
  mdastExtensions: [directiveFromMarkdown]
})

console.log(tree)

const out = toMarkdown(tree, {extensions: [directiveToMarkdown]})

console.log(out)

Now, running node example yields (positional info removed for brevity):

{
  type: 'root',
  children: [
    {
      type: 'paragraph',
      children: [
        {type: 'text', value: 'A lovely language know as '},
        {
          type: 'textDirective',
          name: 'abbr',
          attributes: {title: 'HyperText Markup Language'},
          children: [{type: 'text', value: 'HTML'}]
        },
        {type: 'text', value: '.'}
      ]
    }
  ]
}
A lovely language know as :abbr[HTML]{title="HyperText Markup Language"}.

API

directiveFromMarkdown

directiveToMarkdown

Support the generic directives proposal. The exports are extensions, respectively for mdast-util-from-markdown and mdast-util-to-markdown.

There are no options, but passing options.quote to mdast-util-to-markdown is honored for attributes.

This utility handles parsing and serializing. Traverse the tree to change them to whatever you please.

Syntax tree

The following interfaces are added to mdast by this utility.

Nodes

TextDirective

interface TextDirective <: Parent {
  type: 'textDirective'
  children: [PhrasingContent]
}

TextDirective includes Directive

TextDirective (Parent) is a directive. It can be used where phrasing content is expected. Its content model is also phrasing content. It includes the mixin Directive.

For example, the following Markdown:

:name[Label]{#x.y.z key=value}

Yields:

{
  type: 'textDirective',
  name: 'name',
  attributes: {id: 'x', class: 'y z', key: 'value'},
  children: [{type: 'text', value: 'Label'}]
}

LeafDirective

interface LeafDirective <: Parent {
  type: 'leafDirective'
  children: [PhrasingContent]
}

LeafDirective includes Directive

LeafDirective (Parent) is a directive. It can be used where flow content is expected. Its content model is phrasing content. It includes the mixin Directive.

For example, the following Markdown:

::youtube[Label]{v=123}

Yields:

{
  type: 'leafDirective',
  name: 'youtube',
  attributes: {v: '123'},
  children: [{type: 'text', value: 'Label'}]
}

ContainerDirective

interface ContainerDirective <: Parent {
  type: 'containerDirective'
  children: [FlowContent]
}

ContainerDirective includes Directive

ContainerDirective (Parent) is a directive. It can be used where flow content is expected. Its content model is also flow content. It includes the mixin Directive.

The phrasing in the label is, when available, added as a paragraph with a directiveLabel: true field, as the head of its content.

For example, the following Markdown:

:::spoiler[Open at your own peril]
He dies.
:::

Yields:

{
  type: 'containerDirective',
  name: 'spoiler',
  attributes: {},
  children: [
    {
      type: 'paragraph',
      data: {directiveLabel: true},
      children: [{type: 'text', value: 'Open at your own peril'}]
    },
    {
      type: 'paragraph',
      children: [{type: 'text', value: 'He dies.'}]
    }
  ]
}

Mixin

Directive

interface mixin Directive {
  name: string
  attributes: Attributes?
}

interface Attributes {}
typedef string AttributeName
typedef string AttributeValue

Directive represents something defined by an extension.

The name field must be present and represents an identifier of an extension.

The attributes field represents information associated with the node. The value of the attributes field implements the Attributes interface.

In the Attributes interface, every field must be an AttributeName and every value an AttributeValue. The fields and values can be anything: there are no semantics (such as by HTML or hast).

In JSON, the value null must be treated as if the attribute was not included. In JavaScript, both null and undefined must be similarly ignored.

Contribute

See contributing.md in syntax-tree/.github for ways to get started. See support.md for ways to get help.

This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.

License

MIT © Titus Wormer