Search code examples
node.jsnunjucks

Nunjucks : How to bypass autoescape with custom extension?


I managed to make async custom extension in Nunjucks.js and I still have some unanswered questions. The following one is one of them.

How do you configure your extension to not be escaping its output. My code looks something like that.

var nunjucks = require('nunjucks');

module.exports = function CustomExtension() {
this.tags = ['docs'];

this.parse = function(parser, nodes, lexer) {


    // parse the args and move after the block end. passing true
    // as the second arg is required if there are no parentheses
    var args = parser.parseSignature(null, true);

    parser.nextToken();


    // parse the content until end block

    var body = parser.parseUntilBlocks('enddocs');

    parser.advanceAfterBlockEnd();

    return new nodes.CallExtensionAsync(this, 'run', args, [body]);
};

this.run = function(context, arguments, body, callback) {


    var id = body();

    somAsyncMagic(id, function(html) {

        callback(null, html);

    });


};

}

This piece of code is used in node by the way. If that may spark some idea to someone.

Thanks


Solution

  • You have access to all internal filters, so the answer is cb(null, nunjucks.filters.safe(html));.

    var nunjucks = require('nunjucks');
    
    var MyLoader = nunjucks.Loader.extend({
        async: true,
        getSource: function(name, callback) {
            var res = '...';
            callback(err, res);
        }
    });
    
    var env = new nunjucks.Environment(new MyLoader(), {autoescape: true}); // !
    
    function CustomExtension(cb) {
        this.tags = ['docs'];
    
        this.parse = function(parser, nodes, lexer) {
            var tok = parser.nextToken();
            var args = parser.parseSignature(null, true);
            parser.nextToken();
            var body = parser.parseUntilBlocks('enddocs');
            parser.advanceAfterBlockEnd();
            return new nodes.CallExtensionAsync(this, 'run', args, [body], cb);
        };
    
        this.run = function(context, args, body, cb) {
            var res = env.filters.safe(args + ':' + body()); // prevent escape
            cb(null, res);
        };
    }    
    env.addExtension('CustomExtension', new CustomExtension());
    
    env.renderString('{% docs "<TEST>" %}"OK"{% enddocs %}', console.log);