Extensible macro processing framework for markdown, written in TypeScript.
In order to call a macro, you must now precede the text with macro:
. e.g.
\\[[youtube url="url"]]
must now be written as \\[[macro:youtube url="url"]]
.
This is so that we can add support for parsing of wiki-style linking in the future, and so that the macro system does not collide with common markdown applications, which use wiki-style linking.
There have been lots of requests and proposals over the years for an official spec for a rich and extensible version of markdown. People want to be able to write clean and succinct text in their markdown files, and have it rendered into complex html components, without the need for inline html in their markdown files.
- https://stackoverflow.com/questions/24580042/github-markdown-are-macros-and-variables-possible
- https://github.com/howardroark/Markdown-Macros
To John Gruber's (the creator of Markdown) credit, he designed Markdown to be lightweight, and he has stuck to his original spec. It is unlikely we will see an overhaul to the markdown specification that would bring features like macros or more rich rendering capabilities to the markdown language itself.
The best thing about markdown is that it's plain text. It is easy to pre-
or post-
process any markdown text without interfering with other steps of the text processing pipeline. This is how mdmacros
works. Technically, this module can work on any text, not just markdown.
If you want to embed a YouTube video in a markdown document without mdmacros
, you'd do this:
This is my regular markdown document. If I wanted to include
a youtube video embed, this is what I would do today:
<iframe width="560" height="315" src="<youtube-embed-url>"
frameborder="0" allowfullscreen></iframe>
This is not ideal for two reasons:
- This can get hairy for complex markup
- Your content creators shouldnt have to know html to create rich, interactive content.
md-macros
lets you define your own macros that enable you to simplify the same file to this:
This is my super clean markdown document thanks to md-macros!
This is all I need to type in order to include a video.
[[macro:youtube url="<youtube-embed-url>"]]
A clear improvement.
mdmacros is available as a cli or a nodejs module.
You can run the bundled macros against any markdown file with:
mdmacros README.tmpl.md README.md
Out of the box you can use this to insert a table of contents section into your readme, by including a call to the mdToc
macro, or to inline a file with a call to the inlineFile
macro (both are documented below).
[[inlineFile path="./lib/typedefs.ts"]]
async function replaceMacrosInMd(
md: string,
macros: {[key: string]: MacroMethod},
skipMacroNamePatterns: string[] = []
): Promise<string>`
This method is where all of the magic happens.
[[inlineFile path="examples/replace-macros-in-md-usage.ts"]]
function parseMacrosFromMd(md: string): ParsedMacros
[[inlineFile path="examples/parse-macros-from-md-usage.ts"]]
[[inlineFile path="tests/expected-parsed-macros.ts"]]
This package is intended to aid in the markdown processing pipeline by introducing the concept of macros. To that end, it doesn't provide many macros for consumption.
This macros is utilized in the above examples.
url
: the embed url for the YouTube video
This macro takes no arguments, and replaces the macro call with the table of contents for the file.
Inlines the contents of a file into the markdown document. Used within this readme for the Typedefs section.
path
: path to the file to inline
You can easily write your own macro methods. Be sure to specify all macros that you call in your text in the macros
argument to replaceMacrosInMd
when you call it.
Macros are simple functions that take two arguments, and return a Promise for a string (refer to the MacroMethod
typedef above.
The arguments passed to the method are as follows:
args
object. This is a map containing whatever was passed to the macro in the markdown text. Each macro defines what goes in the args object that is passed to itself. The macro should take care to validate that it was passed the proper arguments, and throw if not.mdText: string
. The text for the original markdown document with no replacements having been made. This is useful for macros such as themdToc
macro, which needs the full document in order to generate and return a table of contents.
An example will help illustrate:
[[inlineFile path="examples/creating-macros-usage.ts"]]