all files / lib/ index.js

59.46% Statements 22/37
25% Branches 4/16
75% Functions 3/4
59.46% Lines 22/37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84                                                                                                                            
module.exports = function NunjucksCodeHighlight(nunjucks, hljs) {
    this.tags = ['code'];
 
    this.parse = function(parser, nodes, lexer) {
        // get the tag token
        var tok = parser.nextToken();
 
        // 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.advanceAfterBlockEnd(tok.value);
 
        // If arguments, return the fileTag constructed node
        Iif (args.children.length > 0)
          return new nodes.CallExtension(this, 'fileTag', args);
 
        // parse the body and possibly the error block, which is optional
        var body = parser.parseUntilBlocks('endcode');
 
        // I found Nunjucks  to be incredibly convoluted on how to just get some data into the BlockTag function,
        // this finally worked by faking another template node.
        var tabStart = new nodes.NodeList(0, 0, [new nodes.Output(0, 0, [new nodes.TemplateData(0, 0, (tok.colno - 1))])]);
 
        parser.advanceAfterBlockEnd();
 
        // See above for notes about CallExtension
        return new nodes.CallExtension(this, 'blockTag', args, [ body, tabStart]);
    };
 
    // code rendering for the file tag. Use the nunjucks.render function to render
    // the actual contents of the file. Pass the results through the code renderer.
    // this.fileTag = function(environment, file) {
    //      return new nunjucks.runtime.SafeString(...)
    //    }
 
    // code rendering for the block. Pretty simple, just get the body text and pass
    // it through the code renderer.
    this.blockTag = function(environment, body, tabStart) {
 
      var body = body();
      var spacesRegex = /^[\s]+/;
      var tabStart = tabStart(); // The column postion of the {% code %} tag.
 
      Iif (tabStart > 0) { // If the {% code %} tag is tabbed in, normalize the content to the same depth.
        body = body.split(/\r?\n/); // Split into lines.
        body = body.map(function(line, i) {
          var startSpaces = line.match(spacesRegex);
          if (startSpaces && startSpaces[0].length >= tabStart) { // If the content is not at the same or greater tab depth, do nothing..
            return line.slice(tabStart); // Subtract the column position from the start of the string.
          } else {
            return line;
          }
        });
 
        // remove blank start and end lines to be safe
        if (body[0] === '')
          body = body.slice(1);
        if (body[body.length - 1] === '')
          body = body.slice(0, body.length - 1);
 
        body = body.join("\n"); // Rejoin into one string.
 
      }
 
      // remove line break from start and end of string
      // <http://stackoverflow.com/a/14572494>
      body = body.replace(/^\s+|\s+$/, '');
 
      // get the first line of the body to see if we have a file type specified
      var value = hljs.highlightAuto(body).value;
      Eif (body.split('\n').length > 1) {
        var lang = hljs.getLanguage(body.split('\n')[0]);
        Iif (lang) {
          lang = body.split('\n')[0];
          body = body.split('\n').slice(1).join('\n');
          value = hljs.highlight(lang, body).value;
        }
      }
 
      return new nunjucks.runtime.SafeString('<pre><code class="hljs">' + value + ' </code></pre>');
 
    };
};