[JS] How to add custom tag to Commonmark.js?


#1

How can I add custom tags to commonmark.js? Is commonmark.js the correct way to go about adding custom tags? I’ve had limited success using the walker class in the example below.

For example, I want to provide the user with the ability to type:

[one-third]some text here[/one-third]

and translate it to:

<div class="col-lg-4">some text here</div>

My walker function:

function oneThird(walker){
    while ((event = walker.next())) {
        node = event.node;
        console.log(node);
        console.log(node.literal);      // [, heading1, ]
        //console.log(node.next);
        //console.log(node.next.next);


        if (event.entering && node.type === 'text' && node.literal == "[" && node.next.literal == "one-third" && node.next.next.literal == "]") {
            node.literal = "<div class='col-lg-4'>";
            node.next.next.unlink();
            node.next.unlink();
        }

        if (event.entering && node.type === 'text' && node.literal == "[" && node.next.literal == "/one-third" && node.next.next.literal == "]") {
            node.literal = "</div>";
            node.next.next.unlink();
            node.next.unlink();
        }
    }
}

And then this is used like so:

var reader = new commonmark.Parser();
var writer = new commonmark.HtmlRenderer();
var parsed = reader.parse("Hello *world* [one-third]test[/one-third]"); // parsed is a 'Node' tree

var walker = parsed.walker();
var event, node;
var exitEntering;

oneThird(walker);
/*
Add all of my custom tag functions here
*/

// transform parsed if you like...
var result = writer.render(parsed); // result is a String
console.log(result); // <p>Hello <em>world</em> &lt;div class='col-lg-4'&gt;test[/one-third]</p>

This method doesn’t seem to account for situations in which the user doesn’t add the closing bracket either. Overall I just feel like I’m missing something and there is a better way to do this.

Edit:
Just to add, prior to my last post I came across some issue threads on commonmark.js github page which lead me to believe the renderer object might be a better option than the walker object. But I’m having a difficult time finding information on how to manipulate/extend it. Also, some of those threads are over a year old, so I’m not sure if there have been changes to the implementation since then.





#2

So I’ve been digging through the code some more and realize there are three stages when translating between markdown and HTML.

Markdown -> Parser -> AST (Walker) -> Renderer -> HTML.

However, I’m having a very difficult time figuring out how to extend the default parsers and renderers. I’m finding if I write custom code in the commonmark.js package I can probably achieve what I want, but that’s not really an option because it would all be overwritten when I update the package. I’m starting to think commonmark.js isn’t meant to support custom markdown.

Forgive me if this is simple, but I’m new to node.js. Additionally commonmark.js doesn’t seem to follow the same type of prototype structure as I’m used to in classic clientside JS. Or at least from what I can tell it doesn’t. Could anyone confirm whether commonmark.js supports this or not? Just so I don’t continue to spend time on this if it’s not supported. If it is supported, could you provide any tips, resources or just a general overview of how it should be done.


#3

Just a bump. I still haven’t figured out how to extend the parsers and renderers without hacking up the source code yet. Even if this is not supported or suggested, a confirmation saying so would be greatly appreciated :grin:

Many thanks


#4

It seems that the reference implementation could use some API documentation, but it’s likely that no one has had time for that.


#5

Thanks for the reply. If I figure it out I’ll try to contribute to the documentation then.


#6

@dlanz you can also take a look at markdown-it which allows you to add custom tags (there are several plugins that do just that).