UNPKG

nunjucks-highlight.js

Version:

A custom nunjucks tag to highlight code blocks using highlight.js

88 lines (70 loc) 3.59 kB
module.exports = function NunjucksCodeHighlight (nunjucks, hljs) { this.tags = ["code"]; this.parse = function (parser, nodes) { // 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 if (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, blockTagBody, blockTagTabStart) { var body = blockTagBody(); var spacesRegex = /^[\s]+/; var tabStart = blockTagTabStart(); // The column postion of the {% code %} tag. if (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) { var startSpaces = line.match(spacesRegex); // If the content is not at the same or greater tab depth, do nothing.. if (startSpaces && startSpaces[0].length >= tabStart) { 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; if (body.split("\n").length > 1) { var lang = hljs.getLanguage(body.split("\n")[0]); if (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>"); }; };