Search code examples
markdowndocpad

How to override rendering methods of marked compiler under docpad-plugin-marked?


I would like to extend marked markdown compiler in the docpad-plugin-marked package and ask for a suggestion how to do this most elegantly.

For example, this is how the documentation of marked says to redefine compiling headers:

var marked = require('marked');
var renderer = new marked.Renderer();

renderer.heading = function (text, level) {
  var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');

  return '<h' + level + '><a name="' +
                escapedText +
                 '" class="anchor" href="#' +
                 escapedText +
                 '"><span class="header-link"></span></a>' +
                  text + '</h' + level + '>';
},

console.log(marked('# heading+', { renderer: renderer }));

The expected result:

<h1>
  <a name="heading-" class="anchor" href="#heading-">
    <span class="header-link"></span>
  </a>
  heading+
</h1>

But docpad-plugin-marked has its own instance of marked so I suppose I need to inject there rather than creating my own. Its documentation does not explain this case https://github.com/docpad/docpad-plugin-marked

Does anyone know how to do with it? Thanks!


Solution

  • There is no way to do this right now because the plugin does not accept a custom renderer https://github.com/docpad/docpad-plugin-marked/blob/master/src/marked.plugin.coffee#L26

    You have to modify the plugin to accept an option that lets you make a custom renderer.

    Warning Pseudo code:

     if (config.markedRenderer) {
     // make a new renderer
       renderer = new marked.Renderer();
       Object.keys(config.markedRenderer).forEach(function(key) {
         return renderer[key] = config.markedRenderer[key];
       });
     }
        // set the new renderer
       return marked(opts.content, { renderer: renderer }, function(err, result) {
            opts.content = result;
            return next(err);
          });
    

    And in your config file:

        marked: {
      markedRenderer: {
        heading: function (text, level) {
          var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
    
          return '<h' + level + '><a name="' +
            escapedText +
            '" class="anchor" href="#' +
            escapedText +
            '"><span class="header-link"></span></a>' +
            text + '</h' + level + '>';
        }
      }
    },
    

    If you make this work properly it would make a great pull requests for this plugin!

    Update: I actually needed this functionality, so you can see my fork here: https://github.com/vladikoff/docpad-plugin-marked/commit/39cc54a0856c5ee0bc784920a6156acf1e1e5568#diff-c25561cb097f02c31ba4fa2cf5dce74eR34

    plugins: {
    marked: {
      markedRenderer: {
        heading: function (text, level) {
          var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
    
          return '<h' + level + '>' +
            text + ' <a name="' +
            escapedText +
            '" class="anchor" href="#' +
            escapedText +
            '"><span class="header-link"># </span></a></h' + level + '>';
        }
      }
    },