From 6df79eb8b95b2c36e7395bedcd13e0facb323434 Mon Sep 17 00:00:00 2001 From: Sebastian Pipping Date: Tue, 17 Sep 2013 23:28:18 +0200 Subject: [PATCH 1/3] Add test for issue 25 --- tests/test_ansi2html.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_ansi2html.py b/tests/test_ansi2html.py index 418d69d..5c38c90 100644 --- a/tests/test_ansi2html.py +++ b/tests/test_ansi2html.py @@ -183,5 +183,13 @@ def test_no_markup_lines(self): html = Ansi2HTMLConverter().convert(test, full=False) self.assertEqual(expected, html) + def test_issue_25(self): + sample = '\x1b[0;38;5;238;48;5;231mTEXT\x1b[0m' + + html = Ansi2HTMLConverter(inline=False).convert(sample, full=False) + expected = six.u('TEXT') + + self.assertEqual(expected, html) + if __name__ == '__main__': unittest.main() From 4db97b126c600d30a922ab5899faa8879f699739 Mon Sep 17 00:00:00 2001 From: Sebastian Pipping Date: Mon, 16 Sep 2013 20:15:06 +0200 Subject: [PATCH 2/3] Fix destructive reset marker handling (issue 25) --- ansi2html/converter.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/ansi2html/converter.py b/ansi2html/converter.py index a7f1d9e..4a9cace 100755 --- a/ansi2html/converter.py +++ b/ansi2html/converter.py @@ -1,6 +1,7 @@ # This file is part of ansi2html # Convert ANSI (terminal) colours and attributes to HTML # Copyright (C) 2012 Ralph Bean +# Copyright (C) 2013 Sebastian Pipping # # Inspired by and developed off of the work by pixelbeat and blackjack. # @@ -142,16 +143,32 @@ def _apply_regex(self, ansi): except ValueError: params = [0] - # Special control codes. Mutate into an explicit-color css class. - if params[0] in [38, 48]: - params = ["%i-%i" % (params[0], params[2])] + params[3:] - - if 0 in params: + # Find latest reset marker + last_null_index = None + skip_after_index = -1 + for i, v in enumerate(params): + if i <= skip_after_index: + continue + + if v == 0: + last_null_index = i + elif v in [38, 48]: + skip_after_index = i + 2 + + # Process reset marker, drop everything before + if last_null_index is not None: + params = params[last_null_index + 1:] # If the control code 0 is present, close all tags we've # opened so far. i.e. reset all attributes yield '' * n_open n_open = 0 - continue + + if not params: + continue + + # Special control codes. Mutate into an explicit-color css class. + if params[0] in [38, 48]: + params = ["%i-%i" % (params[0], params[2])] + params[3:] # Count how many tags we're opening n_open += 1 From f277f8f3c4eaa1256c5df66238583b5a69882456 Mon Sep 17 00:00:00 2001 From: Sebastian Pipping Date: Mon, 16 Sep 2013 20:31:40 +0200 Subject: [PATCH 3/3] Fix ANSI code decoding (issue 25) --- ansi2html/converter.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ansi2html/converter.py b/ansi2html/converter.py index 4a9cace..0003486 100755 --- a/ansi2html/converter.py +++ b/ansi2html/converter.py @@ -166,13 +166,25 @@ def _apply_regex(self, ansi): if not params: continue - # Special control codes. Mutate into an explicit-color css class. - if params[0] in [38, 48]: - params = ["%i-%i" % (params[0], params[2])] + params[3:] + # Turn codes into CSS classes + css_classes = [] + skip_after_index = -1 + for i, v in enumerate(params): + if i <= skip_after_index: + continue + + if v in [38, 48]: # 256 color mode switches + try: + css_class = 'ansi%i-%i' % (params[i], params[i + 2]) + except IndexError: + continue + skip_after_index = i + 2 + else: + css_class = 'ansi%d' % v + css_classes.append(css_class) # Count how many tags we're opening n_open += 1 - css_classes = ["ansi%s" % str(p) for p in params] if self.inline: style = [self.styles[klass].kw for klass in css_classes if