summaryrefslogtreecommitdiff
path: root/lib/coderay/encoders/html/numbering.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/coderay/encoders/html/numbering.rb')
-rw-r--r--lib/coderay/encoders/html/numbering.rb118
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/coderay/encoders/html/numbering.rb b/lib/coderay/encoders/html/numbering.rb
new file mode 100644
index 0000000..3a7edce
--- /dev/null
+++ b/lib/coderay/encoders/html/numbering.rb
@@ -0,0 +1,118 @@
+module CodeRay
+module Encoders
+
+ class HTML
+
+ module Output # :nodoc:
+
+ def number! mode = :table, options = {}
+ return self unless mode
+
+ options = DEFAULT_OPTIONS.merge options
+
+ start = options[:line_number_start]
+ unless start.is_a? Integer
+ raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % start
+ end
+
+ anchor_prefix = options[:line_number_anchors]
+ anchor_prefix = 'line' if anchor_prefix == true
+ anchor_prefix = anchor_prefix.to_s[/\w+/] if anchor_prefix
+ anchoring =
+ if anchor_prefix
+ proc do |line|
+ line = line.to_s
+ anchor = anchor_prefix + line
+ "<a href=\"##{anchor}\" name=\"#{anchor}\">#{line}</a>"
+ end
+ else
+ proc { |line| line.to_s }
+ end
+
+ bold_every = options[:bold_every]
+ highlight_lines = options[:highlight_lines]
+ bolding =
+ if bold_every == false && highlight_lines == nil
+ anchoring
+ elsif highlight_lines.is_a? Enumerable
+ highlight_lines = highlight_lines.to_set
+ proc do |line|
+ if highlight_lines.include? line
+ "<strong class=\"highlighted\">#{anchoring[line]}</strong>" # highlighted line numbers in bold
+ else
+ anchoring[line]
+ end
+ end
+ elsif bold_every.is_a? Integer
+ raise ArgumentError, ":bolding can't be 0." if bold_every == 0
+ proc do |line|
+ if line % bold_every == 0
+ "<strong>#{anchoring[line]}</strong>" # every bold_every-th number in bold
+ else
+ anchoring[line]
+ end
+ end
+ else
+ raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every
+ end
+
+ case mode
+ when :inline
+ max_width = (start + line_count).to_s.size
+ line_number = start
+ opened_tags = []
+ gsub!(/^.*$\n?/) do |line|
+ line.chomp!
+ open = opened_tags.join
+ line.scan(%r!<(/)?span[^>]*>?!) do |close,|
+ if close
+ opened_tags.pop
+ else
+ opened_tags << $&
+ end
+ end
+ close = '</span>' * opened_tags.size
+
+ line_number_text = bolding.call line_number
+ indent = ' ' * (max_width - line_number.to_s.size) # TODO: Optimize (10^x)
+ line_number += 1
+ "<span class=\"no\">#{indent}#{line_number_text}</span>#{open}#{line}#{close}\n"
+ end
+
+ when :table
+ line_numbers = (start ... start + line_count).to_a.map(&bolding).join("\n")
+ line_numbers << "\n"
+
+ line_numbers_table_template = TABLE.apply('LINE_NUMBERS', line_numbers)
+ gsub!(/<\/div>\n/) { '</div>' }
+ wrap_in! line_numbers_table_template
+ @wrapped_in = :div
+
+ when :list
+ raise NotImplementedError, 'The :list option is no longer available. Use :table.'
+
+ else
+ raise ArgumentError, 'Unknown value %p for mode: expected one of %p' %
+ [mode, [:table, :inline]]
+ end
+
+ self
+ end
+
+ def line_count
+ line_count = count("\n")
+ position_of_last_newline = rindex(?\n)
+ if position_of_last_newline
+ after_last_newline = self[position_of_last_newline + 1 .. -1]
+ ends_with_newline = after_last_newline[/\A(?:<\/span>)*\z/]
+ line_count += 1 if not ends_with_newline
+ end
+ line_count
+ end
+
+ end
+
+ end
+
+end
+end