Skip to content
This repository

Add colorization of ANSI escape sequences in logs #8

Merged
merged 2 commits into from over 1 year ago

2 participants

Max Riveiro Ian Babrou
Max Riveiro
kavu commented

Added simple colorization of ANSI escape sequences in logs with a help of jquery.colorizeConsoleOutput.js (https://github.com/Guilda/console-output-colorizer).

Max Riveiro Add colorization of ANSI escape sequences in logs
Added simple colorization of ANSI escape sequences in logs
with a help of jquery.colorizeConsoleOutput.js
(https://github.com/Guilda/console-output-colorizer).
f7efc29
Ian Babrou
Owner

File that causes Uncaught TypeError: Cannot call method 'split' of undefined: http://bobrik.name/uploads/ansi-pewpew

Max Riveiro
kavu commented

As far as i now ESC[K stands for clean to the end of line, so HTML doesn't support it, so I can suggest to add replace(/\x1b\[K/g, ''). Btw, later we can filter out all non-color escape codes.

public/js/jquery.colorizeConsoleOutput.js
((294 lines not shown))
  294
+
  295
+// A xterm-256 color sequence is like 38;5;120 or 48;5;120
  296
+ConsoleOutput.prototype.isXterm256ColorSequence = function(sequence) {
  297
+  var codes = sequence.split(';');
  298
+
  299
+  if (codes.length == 3) {
  300
+    var colorCode = parseInt(codes[2]);
  301
+    return (codes[0] == "38" || codes[0] == "48") && (codes[1] == "5") && (colorCode >= 0 && colorCode <= 255)
  302
+  }
  303
+
  304
+  return false;
  305
+}
  306
+
  307
+ConsoleOutput.prototype.toHtml = function() {
  308
+  var htmlContent = this.content;
  309
+  htmlContent = htmlContent.replace(/\x1b\[0m/g, '</span>');
1
Ian Babrou Owner
bobrik added a note

should be htmlContent = htmlContent.replace(/\x1b\[0?m/g, '</span>');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
public/js/jquery.colorizeConsoleOutput.js
((296 lines not shown))
  296
+ConsoleOutput.prototype.isXterm256ColorSequence = function(sequence) {
  297
+  var codes = sequence.split(';');
  298
+
  299
+  if (codes.length == 3) {
  300
+    var colorCode = parseInt(codes[2]);
  301
+    return (codes[0] == "38" || codes[0] == "48") && (codes[1] == "5") && (colorCode >= 0 && colorCode <= 255)
  302
+  }
  303
+
  304
+  return false;
  305
+}
  306
+
  307
+ConsoleOutput.prototype.toHtml = function() {
  308
+  var htmlContent = this.content;
  309
+  htmlContent = htmlContent.replace(/\x1b\[0m/g, '</span>');
  310
+  // Default color should close span also
  311
+  htmlContent = htmlContent.replace(/\x1b\[39m/g, '</span>');
2
Ian Babrou Owner
bobrik added a note

you need to add htmlContent = htmlContent.replace(/\x1b\[K/g, '');

Max Riveiro
kavu added a note

Yeah, it's just the same i suggest in pull request. Btw, It's not my script, I burrowed it :-) Surely i will fix all this nasty things

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
public/js/jquery.colorizeConsoleOutput.js
((299 lines not shown))
  299
+  if (codes.length == 3) {
  300
+    var colorCode = parseInt(codes[2]);
  301
+    return (codes[0] == "38" || codes[0] == "48") && (codes[1] == "5") && (colorCode >= 0 && colorCode <= 255)
  302
+  }
  303
+
  304
+  return false;
  305
+}
  306
+
  307
+ConsoleOutput.prototype.toHtml = function() {
  308
+  var htmlContent = this.content;
  309
+  htmlContent = htmlContent.replace(/\x1b\[0m/g, '</span>');
  310
+  // Default color should close span also
  311
+  htmlContent = htmlContent.replace(/\x1b\[39m/g, '</span>');
  312
+
  313
+  // Regex to match any ANSI espace sequence.
  314
+  regex = new RegExp("\\x1b\\[((\\d+);?(\\d+)?;?(\\d+)?)?m", "g");
1
Ian Babrou Owner
bobrik added a note

global variables sucks: regex, matches

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
public/js/jquery.colorizeConsoleOutput.js
... ...
@@ -0,0 +1,370 @@
  1
+colorMaps = {
1
Ian Babrou Owner
bobrik added a note

this shoud be with var and inside of (function() { })(); to prevent global namespace pollution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Max Riveiro
kavu commented

@bobrik, ping?

Ian Babrou
Owner

So far so good! Merging

Ian Babrou bobrik merged commit 6a9b87c into from
Ian Babrou bobrik closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

Aug 28, 2012
Max Riveiro Add colorization of ANSI escape sequences in logs
Added simple colorization of ANSI escape sequences in logs
with a help of jquery.colorizeConsoleOutput.js
(https://github.com/Guilda/console-output-colorizer).
f7efc29
Aug 29, 2012
Max Riveiro Recreated jquery.colorizeConsoleOutput.js from rewritten CoffeeScript…
… variant
7099a8f
This page is out of date. Refresh to see the latest.
2  README.md
Source Rendered
@@ -54,6 +54,8 @@ PuperGrep needs to know what to monitor. Simple server to make you understand wh
54 54
 
55 55
         // if your log may be interpreted as html:
56 56
         // manager.setLogType("my_cool_log", "html");
  57
+        // or has ANSI escape sequences
  58
+        // manager.setLogType("my_cool_log", "ansi");
57 59
 
58 60
         puper.listen(8080, "127.0.0.1");
59 61
     });
5  public/index.html
@@ -143,6 +143,7 @@
143 143
 
144 144
         <script type="text/javascript" src="/js/jquery.js"></script>
145 145
         <script type="text/javascript" src="/js/jquery.textext.js"></script>
  146
+        <script type="text/javascript" src="/js/jquery.colorizeConsoleOutput.js"></script>
146 147
         <script type="text/javascript" src="/socket.io/socket.io.js"></script>
147 148
         <script type="text/javascript">
148 149
             jQuery(document).ready(function() {
@@ -456,6 +457,10 @@
456 457
                         line.html(text);
457 458
                     }
458 459
 
  460
+                    if (currentLogType == "ansi") {
  461
+                        line.colorizeConsoleOutput();
  462
+                    }
  463
+
459 464
                     if (!isGrepAcceptedLine(text)) {
460 465
                         return;
461 466
                     }
100  public/js/jquery.colorizeConsoleOutput.js
... ...
@@ -0,0 +1,100 @@
  1
+(function() {
  2
+  var ConsoleOutput;
  3
+
  4
+  ConsoleOutput = (function() {
  5
+
  6
+    function ConsoleOutput() {}
  7
+
  8
+    ConsoleOutput.prototype.content = '';
  9
+
  10
+    ConsoleOutput.prototype.colors = {
  11
+      foreground: {
  12
+        30: 'black',
  13
+        31: 'red',
  14
+        32: 'green',
  15
+        33: 'yellow',
  16
+        34: 'blue',
  17
+        35: 'magenta',
  18
+        36: 'cyan',
  19
+        37: 'white'
  20
+      },
  21
+      background: {
  22
+        40: 'black',
  23
+        41: 'red',
  24
+        42: 'green',
  25
+        43: 'yellow',
  26
+        44: 'blue',
  27
+        45: 'magenta',
  28
+        46: 'cyan',
  29
+        47: 'white'
  30
+      },
  31
+      xterm256: ['000000', '800000', '008000', '808000', '000080', '800080', '008080', 'c0c0c0', '808080', 'ff0000', '00ff00', 'ffff00', '0000ff', 'ff00ff', '00ffff', 'ffffff', '000000', '00005f', '000087', '0000af', '0000d7', '0000ff', '005f00', '005f5f', '005f87', '005faf', '005fd7', '005fff', '008700', '00875f', '008787', '0087af', '0087d7', '0087ff', '00af00', '00af5f', '00af87', '00afaf', '00afd7', '00afff', '00d700', '00d75f', '00d787', '00d7af', '00d7d7', '00d7ff', '00ff00', '00ff5f', '00ff87', '00ffaf', '00ffd7', '00ffff', '5f0000', '5f005f', '5f0087', '5f00af', '5f00d7', '5f00ff', '5f5f00', '5f5f5f', '5f5f87', '5f5faf', '5f5fd7', '5f5fff', '5f8700', '5f875f', '5f8787', '5f87af', '5f87d7', '5f87ff', '5faf00', '5faf5f', '5faf87', '5fafaf', '5fafd7', '5fafff', '5fd700', '5fd75f', '5fd787', '5fd7af', '5fd7d7', '5fd7ff', '5fff00', '5fff5f', '5fff87', '5fffaf', '5fffd7', '5fffff', '870000', '87005f', '870087', '8700af', '8700d7', '8700ff', '875f00', '875f5f', '875f87', '875faf', '875fd7', '875fff', '878700', '87875f', '878787', '8787af', '8787d7', '8787ff', '87af00', '87af5f', '87af87', '87afaf', '87afd7', '87afff', '87d700', '87d75f', '87d787', '87d7af', '87d7d7', '87d7ff', '87ff00', '87ff5f', '87ff87', '87ffaf', '87ffd7', '87ffff', 'af0000', 'af005f', 'af0087', 'af00af', 'af00d7', 'af00ff', 'af5f00', 'af5f5f', 'af5f87', 'af5faf', 'af5fd7', 'af5fff', 'af8700', 'af875f', 'af8787', 'af87af', 'af87d7', 'af87ff', 'afaf00', 'afaf5f', 'afaf87', 'afafaf', 'afafd7', 'afafff', 'afd700', 'afd75f', 'afd787', 'afd7af', 'afd7d7', 'afd7ff', 'afff00', 'afff5f', 'afff87', 'afffaf', 'afffd7', 'afffff', 'd70000', 'd7005f', 'd70087', 'd700af', 'd700d7', 'd700ff', 'd75f00', 'd75f5f', 'd75f87', 'd75faf', 'd75fd7', 'd75fff', 'd78700', 'd7875f', 'd78787', 'd787af', 'd787d7', 'd787ff', 'd7af00', 'd7af5f', 'd7af87', 'd7afaf', 'd7afd7', 'd7afff', 'd7d700', 'd7d75f', 'd7d787', 'd7d7af', 'd7d7d7', 'd7d7ff', 'd7ff00', 'd7ff5f', 'd7ff87', 'd7ffaf', 'd7ffd7', 'd7ffff', 'ff0000', 'ff005f', 'ff0087', 'ff00af', 'ff00d7', 'ff00ff', 'ff5f00', 'ff5f5f', 'ff5f87', 'ff5faf', 'ff5fd7', 'ff5fff', 'ff8700', 'ff875f', 'ff8787', 'ff87af', 'ff87d7', 'ff87ff', 'ffaf00', 'ffaf5f', 'ffaf87', 'ffafaf', 'ffafd7', 'ffafff', 'ffd700', 'ffd75f', 'ffd787', 'ffd7af', 'ffd7d7', 'ffd7ff', 'ffff00', 'ffff5f', 'ffff87', 'ffffaf', 'ffffd7', 'ffffff', '080808', '121212', '1c1c1c', '262626', '303030', '3a3a3a', '444444', '4e4e4e', '585858', '626262', '6c6c6c', '767676', '808080', '8a8a8a', '949494', '9e9e9e', 'a8a8a8', 'b2b2b2', 'bcbcbc', 'c6c6c6', 'd0d0d0', 'dadada', 'e4e4e4', 'eeeeee']
  32
+    };
  33
+
  34
+    ConsoleOutput.prototype.isXterm256ColorSequence = function(sequence) {
  35
+      var codes, colorCode;
  36
+      codes = sequence.split(';');
  37
+      if (codes.length === 3) {
  38
+        colorCode = parseInt(codes[2]);
  39
+        return (codes[0] === "38" || codes[0] === "48") && (codes[1] === "5") && (colorCode >= 0 && colorCode <= 255);
  40
+      }
  41
+      return false;
  42
+    };
  43
+
  44
+    ConsoleOutput.prototype.toHtml = function() {
  45
+      var bgColor, code, codes, colorCode, fgColor, htmlContent, match, matches, regex, style, _i, _len;
  46
+      htmlContent = this.content;
  47
+      htmlContent = htmlContent.replace(/\x1b\[K/g, '');
  48
+      htmlContent = htmlContent.replace(/\x1b\[0?m/g, '</span>');
  49
+      htmlContent = htmlContent.replace(/\x1b\[39m/g, '</span>');
  50
+      regex = new RegExp("\\x1b\\[((\\d+);?(\\d+)?;?(\\d+)?)?m", "g");
  51
+      while ((matches = regex.exec(htmlContent)) !== null) {
  52
+        fgColor = null;
  53
+        bgColor = null;
  54
+        style = [];
  55
+        if (this.isXterm256ColorSequence(matches[1])) {
  56
+          codes = matches[1].split(';');
  57
+          colorCode = parseInt(codes[2]);
  58
+          if (codes[0] === '38') {
  59
+            fgColor = '#' + this.colors.xterm256[colorCode];
  60
+          } else {
  61
+            bgColor = '#' + this.colors.xterm256[colorCode];
  62
+          }
  63
+        } else {
  64
+          for (_i = 0, _len = matches.length; _i < _len; _i++) {
  65
+            match = matches[_i];
  66
+            code = parseInt(match);
  67
+            if (this.colors.foreground[code]) {
  68
+              fgColor = this.colors.foreground[code];
  69
+            } else if (this.colors.background[code]) {
  70
+              bgColor = this.colors.background[code];
  71
+            }
  72
+          }
  73
+        }
  74
+        if (fgColor) {
  75
+          style.push('color: ' + fgColor);
  76
+        }
  77
+        if (bgColor) {
  78
+          style.push('background-color: ' + bgColor);
  79
+        }
  80
+        htmlContent = style.length > 0 ? htmlContent.replace(new RegExp("\\x1b\\[" + matches[1] + "m", 'g'), "<span style=\"" + (style.join('; ')) + "\">") : htmlContent.replace(new RegExp("\\x1b\\[" + matches[1] + "m", 'g'), '<span>');
  81
+      }
  82
+      return htmlContent;
  83
+    };
  84
+
  85
+    return ConsoleOutput;
  86
+
  87
+  })();
  88
+
  89
+  window.ConsoleOutput = ConsoleOutput;
  90
+
  91
+  jQuery.fn.colorizeConsoleOutput = function() {
  92
+    return this.each(function() {
  93
+      var consoleOutput;
  94
+      consoleOutput = new ConsoleOutput();
  95
+      consoleOutput.content = $(this).html();
  96
+      return $(this).html(consoleOutput.toHtml());
  97
+    });
  98
+  };
  99
+
  100
+}).call(this);
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.