highlight.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. 'use strict'
  2. var redeyed = require('redeyed')
  3. var theme = require('../themes/default')
  4. var colors = require('ansicolors')
  5. var colorSurround = colors.brightBlack
  6. var surroundClose = '\u001b[39m'
  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. }
  13. // put the non-empty line back
  14. if (line) lines.push(line)
  15. }
  16. function addLinenos(highlightedCode, firstline) {
  17. var highlightedLines = highlightedCode.split('\n')
  18. trimEmptyLines(highlightedLines)
  19. var linesLen = highlightedLines.length
  20. var lines = []
  21. var totalDigits
  22. var lineno
  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. try {
  54. var result = redeyed(code, opts.theme || theme, { jsx: !!opts.jsx })
  55. var firstline = opts.firstline && !isNaN(opts.firstline) ? opts.firstline : 1
  56. return opts.linenos ? addLinenos(result.code, firstline) : result.code
  57. } catch (e) {
  58. e.message = 'Unable to perform highlight. The code contained syntax errors: ' + e.message
  59. throw e
  60. }
  61. }