remark-ast-express

An experimental package for adding nodes and values to a abstract syntax tree from template expressions, via a unified parser of the kind exposed by remark.


Keywords
remark, plugin, unified, markdown, template
License
0BSD
Install
npm install remark-ast-express@0.0.0

Documentation

remark-ast-inline

An experimental package for adding nodes and values to a abstract syntax tree from template expressions, via a unified parser of the kind exposed by remark.

Usage

Import

import rai from 'remark-ast-express'

Configure

const md = rai({
  converter // Optional
})

function converter(value) {
  return { type: 'value', value: value }
}

The converter function is called (if present) with all the expressions that would be inserted into your template string. It can return either an unist node (an object with a type field containing a string) to later be inserted into the AST or a value to be inserted into the string. For example, to make this package completely useless:

function converter(value) {
  return String(value) // Can't just be `return value` or nodes would still be inserted.
)

Process Text

let { string, astInserter } = md`\
# This is some markdown...
I'm going to insert a value into the AST riiight ${"foobar"}here.

${{
  type: 'strong',
  children: [{type: 'text', value: 'not here'}]
}}
`

import remark from 'remark'
 
let tree = remark()
  .use(...others...)
  .use(astInserter) // The plugin returned above should be last
  .parse(string) // The exact(!) string returned above

Gives:

{
  "type": "root",
  "children": [
    {
      "type": "heading",
      "depth": 1,
      "children": [
        {
          "type": "text",
          "value": "This is some markdown...",
          "position": ...
        }
      ],
      "position": ...
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "text",
          "value": "I'm going to insert a value into the AST riiight ",
          "position": ...
        },
        {
          "type": "value",
          "value": "foobar",
          "position": ...
        },
        {
          "type": "text",
          "value": "here.",
          "position": ...
        }
      ],
      "position": ...
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "value",
          "value": {
            "type": "strong",
            "children": [
              {
                "type": "text",
                "value": "not here"
              }
            ]
          },
          "position": ...
        }
      ],
      "position": ...
    }
  ],
  "position": ...
}

Or, with no converter:

{
  "type": "root",
  "children": [
    {
      "type": "heading",
      "depth": 1,
      "children": [
        {
          "type": "text",
          "value": "This is some markdown...",
          "position": ...
        }
      ],
      "position": ...
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "text",
          "value": "I'm going to insert a value into the AST riiight foobarhere.",
          "position": ...
        }
      ],
      "position": ...
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "strong",
          "children": [
            {
              "type": "text",
              "value": "not here"
            }
          ],
          "position": ...
        }
      ],
      "position": ...
    }
  ],
  "position": ...
}

WTF? Why?

Well, this gives you a nice(ish) syntax in vanilla Javascript for programmatically inserting nodes into the AST inline; which might be useful...? I'm considering using it to implement a React/JS+Markdown website templating framework; it was the least awkward way to hack something together that I may like more than the alternatives (e.g. MDX).

How?

The code inserts tokens of the form <[prefix]:[index]> into the string, where the prefix is a random alphabetic (upper and lower) string that occurs nowhere else in the string (same across the tokens) and the index corresponds to which node should be inserted there. A prefix string and nodes array fields are included in the tag function output.