Skip to content

Commit

Permalink
implement Term::Ansicolor.to_html,
Browse files Browse the repository at this point in the history
ANSI-sequences convert to html string.
  • Loading branch information
hotchpotch committed Jul 21, 2011
1 parent ca74c4c commit 4641ddb
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
23 changes: 22 additions & 1 deletion lib/term/ansicolor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
module Term
# The ANSIColor module can be used for namespacing and mixed into your own
# classes.

# autoloading Term::ANSIColor::HTML
autoload :HTML, 'term/ansicolor/html'

module ANSIColor
# :stopdoc:
ATTRIBUTES = [
Expand Down Expand Up @@ -75,7 +79,7 @@ def #{c}(string = nil)

# Regular expression that is used to scan for ANSI-sequences while
# uncoloring strings.
COLORED_REGEXP = /\e\[(?:[34][0-7]|[0-9])?m/
COLORED_REGEXP = /\e\[([34][0-7]|[0-9])?m/

# Returns an uncolored version of the string, that is all
# ANSI-sequences are stripped from the string.
Expand All @@ -91,6 +95,23 @@ def uncolored(string = nil) # :yields:
end
end

# Return html string
# options[:no_style] = true #=> no render style attribute
def to_html(string = nil, options = {})
target = if block_given?
options = string if string.kind_of?(Hash)
yield
elsif string && !string.kind_of?(Hash)
string
elsif respond_to?(:to_str)
options = string if string.kind_of?(Hash)
to_str
else
''
end
HTML.convert(target, options)
end

module_function

# Returns an array of all Term::ANSIColor attributes as symbols.
Expand Down
72 changes: 72 additions & 0 deletions lib/term/ansicolor/html.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

module Term
module ANSIColor
# HTML convert module
module HTML
ATTRIBUTE_VALUES = ATTRIBUTES.transpose.last

# html escape chars/values
ESC = {
'&' => '&',
'"' => '"',
'<' => '&lt;',
'>' => '&gt;'
}
ESC_KEYS = ESC.keys.join('')

# escape sequences convert to html
def self.convert(string, options = {})
render_style_attributes = !options[:no_style]

escape_html(string).gsub(COLORED_REGEXP) {|m|
span_tag($1.to_i, render_style_attributes)
}
end

# generate span tag from escape sequences number
def self.span_tag(num, render_style_attributes)
if num == 0
"</span>"
else
"<span #{klass(num)}#{render_style_attributes ? style(num) : ''}>"
end
end

# generate class attribute from escape sequences number
def self.klass(num)
name = ATTRIBUTE_NAMES[ATTRIBUTE_VALUES.index(num)].to_s.gsub('_', '-')
%Q|class="ansi-color ansi-#{name}"|
end

# generate style attribute from escape sequences number
def self.style(num)
name = ATTRIBUTE_NAMES[ATTRIBUTE_VALUES.index(num)].to_s
val = nil
case name
when "bold"
val = "font-weight: bold"
when "underline"
val = "text-decoration: underline"
when "blink"
val = "text-decoration: blink"
else
if num >= 10
if m = name.match(/^on_(.*)$/)
val = "background-color: #{m[1]}"
else
val = "color: #{name}"
end
end
end
val ? %Q| style="#{val}"| : ""
end

# escape html chars
def self.escape_html(string)
string.gsub(/[#{ESC_KEYS}]/n) {|c| ESC[c] }
end

extend self
end
end
end
28 changes: 28 additions & 0 deletions tests/ansicolor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,34 @@ def test_uncolored
assert_equal string, uncolored { string }
end

def test_html_red
red_html = '<span class="ansi-color ansi-red" style="color: red">red</span>'
assert_equal red_html, @string_red.to_html
assert_equal red_html, Term::ANSIColor.to_html(@string_red)
assert_equal red_html, Term::ANSIColor.to_html { @string_red }
end

def test_html_red_on_green
red_on_green_html = '<span class="ansi-color ansi-on-green" style="background-color: green"><span class="ansi-color ansi-red" style="color: red">red</span></span>'
assert_equal red_on_green_html, @string_red_on_green.to_html
assert_equal red_on_green_html, Term::ANSIColor.to_html(@string_red_on_green)
assert_equal red_on_green_html, Term::ANSIColor.to_html { @string_red_on_green }
end

def test_html_with_options
options = {:no_style => true}
red_html = '<span class="ansi-color ansi-red">red</span>'
assert_equal red_html, @string_red.to_html(options)
assert_equal red_html, Term::ANSIColor.to_html(@string_red, options)
assert_equal red_html, Term::ANSIColor.to_html(options) { @string_red }
end

def test_html_styles
assert_equal ' style="font-weight: bold"', Term::ANSIColor::HTML.style(1)
assert_equal ' style="text-decoration: underline"', Term::ANSIColor::HTML.style(4)
assert_equal ' style="text-decoration: blink"', Term::ANSIColor::HTML.style(5)
end

def test_attributes
foo = 'foo'
for (a, _) in Term::ANSIColor.attributes
Expand Down

0 comments on commit 4641ddb

Please sign in to comment.