highlight.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. var redeyed = require('redeyed')
  2. , theme = require('../themes/default')
  3. , colors = require('ansicolors')
  4. , colorSurround = colors.brightBlack
  5. , surroundClose = '\u001b[39m'
  6. ;
  7. function trimEmptyLines(lines) {
  8. // remove lines from the end until we find a non-empy one
  9. var line = lines.pop();
  10. while(!line || !line.length)
  11. line = lines.pop();
  12. // put the non-empty line back
  13. if (line) lines.push(line);
  14. }
  15. function addLinenos (highlightedCode, firstline) {
  16. var highlightedLines = highlightedCode.split('\n');
  17. trimEmptyLines(highlightedLines);
  18. var linesLen = highlightedLines.length
  19. , lines = []
  20. , totalDigits
  21. , lineno
  22. ;
  23. function getDigits (n) {
  24. if (n < 10) return 1;
  25. if (n < 100) return 2;
  26. if (n < 1000) return 3;
  27. if (n < 10000) return 4;
  28. // this works for up to 99,999 lines - any questions?
  29. return 5;
  30. }
  31. function pad (n, totalDigits) {
  32. // not pretty, but simple and should perform quite well
  33. var padDigits= totalDigits - getDigits(n);
  34. switch(padDigits) {
  35. case 0: return '' + n;
  36. case 1: return ' ' + n;
  37. case 2: return ' ' + n;
  38. case 3: return ' ' + n;
  39. case 4: return ' ' + n;
  40. case 5: return ' ' + n;
  41. }
  42. }
  43. totalDigits = getDigits(linesLen + firstline - 1);
  44. for (var i = 0; i < linesLen; i++) {
  45. // Don't close the escape sequence here in order to not break multi line code highlights like block comments
  46. lineno = colorSurround(pad(i + firstline, totalDigits) + ': ').replace(surroundClose, '');
  47. lines.push(lineno + highlightedLines[i]);
  48. }
  49. return lines.join('\n');
  50. }
  51. module.exports = function highlight (code, opts) {
  52. opts = opts || { };
  53. if (opts.json) {
  54. code = '!\n' + code;
  55. }
  56. try {
  57. var result = redeyed(code, opts.theme || theme)
  58. , firstline = opts.firstline && !isNaN(opts.firstline) ? opts.firstline : 1;
  59. if (opts.json) {
  60. result.code = result.code.split('\n').slice(1).join('\n');
  61. }
  62. return opts.linenos ? addLinenos(result.code, firstline) : result.code;
  63. } catch (e) {
  64. e.message = 'Unable to perform highlight. The code contained syntax errors: ' + e.message;
  65. throw e;
  66. }
  67. };