summaryrefslogtreecommitdiff
path: root/lib/coderay/encoders/html/numerization.rb
blob: c5d96f3219cf082cbafc8eabd9bcfef4d174e866 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module CodeRay
module Encoders

	class HTML
		
		module Output

			def numerize *args
				clone.numerize!(*args)
			end

=begin			NUMERIZABLE_WRAPPINGS = {
				:table => [:div, :page, nil],
				:inline => :all,
				:list => [:div, :page, nil]
			}
			NUMERIZABLE_WRAPPINGS.default = :all
=end			
			def numerize! 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
				
				#allowed_wrappings = NUMERIZABLE_WRAPPINGS[mode]
				#unless allowed_wrappings == :all or allowed_wrappings.include? options[:wrap]
				#	raise ArgumentError, "Can't numerize, :wrap must be in %p, but is %p" % [NUMERIZABLE_WRAPPINGS, options[:wrap]]
				#end
				
				bold_every = options[:bold_every]
				bolding = 
					if bold_every == false
						proc { |line| line.to_s }
					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>#{line}</strong>"  # every bold_every-th number in bold
							else
								line.to_s
							end
						end
					else
						raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every
					end
				
				line_count = count("\n")
				line_count += 1 unless self[-1] == ?\n

				case mode				
				when :inline
					max_width = (start + line_count).to_s.size
					line = start
					gsub!(/^/) do
						line_number = bolding.call line
						line += 1
						"<span class=\"no\">#{ line_number.rjust(max_width) }</span>  "
					end
					
				when :table
					# This is really ugly.
					# Because even monospace fonts seem to have different heights when bold, 
					# I make the newline bold, both in the code and the line numbers.
					# FIXME Still not working perfect for Mr. Internet Exploder
					# FIXME Firefox struggles with very long codes (> 200 lines)
					line_numbers = (start ... start + line_count).to_a.map(&bolding).join("\n")
					line_numbers << "\n"  # also for Mr. MS Internet Exploder :-/
					line_numbers.gsub!(/\n/) { "<tt>\n</tt>" }
					
					line_numbers_table_tpl = TABLE.apply('LINE_NUMBERS', line_numbers)
					gsub!(/\n/) { "<tt>\n</tt>" }
					wrap_in! line_numbers_table_tpl
					@wrapped_in = :div
					
				when :list
					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
						
						"<li>#{open}#{line}#{close}</li>"
					end
					wrap_in! LIST
					@wrapped_in = :div
					
				else
					raise ArgumentError, 'Unknown value %p for mode: expected one of %p' %
						[mode, [:table, :list, :inline]]
				end

				self
			end

		end

	end

end
end