'use strict' var redeyed = require('redeyed') var theme = require('../themes/default') var colors = require('ansicolors') var colorSurround = colors.brightBlack var surroundClose = '\u001b[39m' function trimEmptyLines(lines) { // remove lines from the end until we find a non-empy one var line = lines.pop() while (!line || !line.length) { line = lines.pop() } // put the non-empty line back if (line) lines.push(line) } function addLinenos(highlightedCode, firstline) { var highlightedLines = highlightedCode.split('\n') trimEmptyLines(highlightedLines) var linesLen = highlightedLines.length var lines = [] var totalDigits var lineno function getDigits(n) { if (n < 10) return 1 if (n < 100) return 2 if (n < 1000) return 3 if (n < 10000) return 4 // this works for up to 99,999 lines - any questions? return 5 } function pad(n, totalDigits) { // not pretty, but simple and should perform quite well var padDigits = totalDigits - getDigits(n) switch (padDigits) { case 0: return '' + n case 1: return ' ' + n case 2: return ' ' + n case 3: return ' ' + n case 4: return ' ' + n case 5: return ' ' + n } } totalDigits = getDigits(linesLen + firstline - 1) for (var i = 0; i < linesLen; i++) { // Don't close the escape sequence here in order to not break multi line code highlights like block comments lineno = colorSurround(pad(i + firstline, totalDigits) + ': ').replace(surroundClose, '') lines.push(lineno + highlightedLines[i]) } return lines.join('\n') } module.exports = function highlight(code, opts) { opts = opts || { } try { var result = redeyed(code, opts.theme || theme, { jsx: !!opts.jsx }) var firstline = opts.firstline && !isNaN(opts.firstline) ? opts.firstline : 1 return opts.linenos ? addLinenos(result.code, firstline) : result.code } catch (e) { e.message = 'Unable to perform highlight. The code contained syntax errors: ' + e.message throw e } }