Marked: Custom InlineLexer Rule

Created on 22 Oct 2014  路  4Comments  路  Source: markedjs/marked

With Marked I can easily ovverride/add/change lexer rules during implementation, and its great!
For example I can force to use space between hash sign an text to make a header like this:

        var lexer = new marked.Lexer(options);
        console.log(lexer);
        lexer.rules.heading = /^\s*(#{1,6})\s+([^\n]+?) *#* *(?:\n+|$)/

        console.log(marked.parser(lexer.lex('#hashtag?'), options));
        //<p>#hashtag?</p>
        console.log(marked.parser(lexer.lex('# heading?'), options));
        //<h1 id="undefinedheading-">heading?</h1>

Cool!
But is there a way, to easily do same for inline lexer?
Like i need to make people be able to add an images with next sequence: %[My Image](http://example.com/img.jpg)?
So i modified:

var inlineLexer = marked.InlineLexer;
        inlineLexer.rules.link = /^[!%]{0,1}?\[((?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*)\]\(\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*\)/;

What should I do next?
How to bind a custom inlineLexer to a marked instance?
Please show me an example of how to do this! How can I modify/add custom inline lexer rules?

Most helpful comment

Actually there is a way without editing the code of marked itself, if you overwrite the prototype. (In this example I surpress parsing of em tags).

marked.prototype.constructor.Parser.prototype.parse = function (src) {
    this.inline = new marked.InlineLexer(src.links, this.options, this.renderer);
    this.inline.rules.em = { exec: $.noop }
    this.tokens = src.reverse();

    var out = '';
    while (this.next()) {
        out += this.tok();
    }

    return out;
};

All 4 comments

I'm pretty sure there is no way to do this without editing the code itself.
The use of the InlineLexer is hardcoded inside the parser.parse function:

https://github.com/chjj/marked/blob/7be419324986c7a37c8d3e2fd580e925e236db52/lib/marked.js#L918

Actually there is a way without editing the code of marked itself, if you overwrite the prototype. (In this example I surpress parsing of em tags).

marked.prototype.constructor.Parser.prototype.parse = function (src) {
    this.inline = new marked.InlineLexer(src.links, this.options, this.renderer);
    this.inline.rules.em = { exec: $.noop }
    this.tokens = src.reverse();

    var out = '';
    while (this.next()) {
        out += this.tok();
    }

    return out;
};

@dotcore 's method solved my problem.
For people coming later, after overriding the constructor, you can also add custom renderer.

var marked = require('marked');

//Override buildin parser constructor
marked.prototype.constructor.Parser.prototype.parse = function (src) {
    this.inline = new marked.InlineLexer(src.links, this.options, this.renderer);
    //custom rule/syntax
    this.inline.rules.link = /^[!@]?\[((?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*)\]\(\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*\)/;
    this.tokens = src.reverse();

    var out = '';
    while (this.next()) {
        out += this.tok();
    }

    return out;
};

//Customize the outputLink Inline lexer
marked.InlineLexer.prototype.outputLink = function(cap, link) {
  var href = escape(link.href)
    , title = link.title ? escape(link.title) : null;

  console.log(title);

  if (cap[0].charAt(0) === '@') {
    return this.renderer.articles(
        cap[1],
        cap[2]
    );
  }

  return cap[0].charAt(0) !== '!'
    ? this.renderer.link(href, title, this.output(cap[1]))
    : this.renderer.image(href, title, escape(cap[1]));
};

//Add renderer for the new rule.
marked.Renderer.prototype.articles = function(title, parameters) {
  let json = JSON.parse(parameters);
  return '<h1 id="articles"'
    + ' paginable="' + json.paginable + '"'
    + ' pageSize="' + json.pageSize + '"'
    + '>'
    + title
    + '</h1>\n';
};

console.log(marked('@[articleComponent]({"paginable":true, "pagsSize":3, "title":"Articles of Doctors"})'));
/*
output is:

<p><h1 id="articles" paginable="true" pageSize="undefined">articleComponent</h1>
</p>
*/

Closing as not part of the current focus. See #1106 and #1216

Was this page helpful?
0 / 5 - 0 ratings