2
2
3
3
module CodeRay
4
4
module Encoders
5
-
5
+
6
6
# = HTML Encoder
7
7
#
8
8
# This is CodeRay's most important highlighter:
@@ -15,7 +15,7 @@ module Encoders
15
15
# puts CodeRay.scan('Some /code/', :ruby).html(:wrap => :span)
16
16
# #-> <span class="CodeRay"><span class="co">Some</span> /code/</span>
17
17
# puts CodeRay.scan('Some /code/', :ruby).span #-> the same
18
- #
18
+ #
19
19
# puts CodeRay.scan('Some code', :ruby).html(
20
20
# :wrap => nil,
21
21
# :line_numbers => :inline,
@@ -26,7 +26,7 @@ module Encoders
26
26
#
27
27
# === :tab_width
28
28
# Convert \t characters to +n+ spaces (a number.)
29
- #
29
+ #
30
30
# Default: 8
31
31
#
32
32
# === :css
@@ -42,13 +42,13 @@ module Encoders
42
42
# Default: nil
43
43
#
44
44
# === :title
45
- #
45
+ #
46
46
# The title of the HTML page (works only when :wrap is set to :page.)
47
47
#
48
48
# Default: 'CodeRay output'
49
49
#
50
50
# === :break_lines
51
- #
51
+ #
52
52
# Split multiline blocks at line breaks.
53
53
# Forced to true if :line_numbers option is set to :inline.
54
54
#
@@ -78,10 +78,10 @@ module Encoders
78
78
# Default: 10
79
79
#
80
80
# === :highlight_lines
81
- #
81
+ #
82
82
# Highlights certain line numbers.
83
83
# Can be any Enumerable, typically just an Array or Range, of numbers.
84
- #
84
+ #
85
85
# Bolding is deactivated when :highlight_lines is set. It only makes sense
86
86
# in combination with :line_numbers.
87
87
#
@@ -94,45 +94,45 @@ module Encoders
94
94
#
95
95
# Default: false
96
96
class HTML < Encoder
97
-
97
+
98
98
register_for :html
99
-
99
+
100
100
FILE_EXTENSION = 'snippet.html'
101
-
101
+
102
102
DEFAULT_OPTIONS = {
103
103
:tab_width => 8 ,
104
-
104
+
105
105
:css => :class ,
106
106
:style => :alpha ,
107
107
:wrap => nil ,
108
108
:title => 'CodeRay output' ,
109
-
109
+
110
110
:break_lines => false ,
111
-
111
+
112
112
:line_numbers => nil ,
113
113
:line_number_anchors => 'n' ,
114
114
:line_number_start => 1 ,
115
115
:bold_every => 10 ,
116
116
:highlight_lines => nil ,
117
-
117
+
118
118
:hint => false ,
119
119
}
120
-
120
+
121
121
autoload :Output , CodeRay . coderay_path ( 'encoders' , 'html' , 'output' )
122
122
autoload :CSS , CodeRay . coderay_path ( 'encoders' , 'html' , 'css' )
123
123
autoload :Numbering , CodeRay . coderay_path ( 'encoders' , 'html' , 'numbering' )
124
-
124
+
125
125
attr_reader :css
126
-
126
+
127
127
protected
128
-
128
+
129
129
HTML_ESCAPE = { #:nodoc:
130
130
'&' => '&' ,
131
131
'"' => '"' ,
132
132
'>' => '>' ,
133
133
'<' => '<' ,
134
134
}
135
-
135
+
136
136
# This was to prevent illegal HTML.
137
137
# Strange chars should still be avoided in codes.
138
138
evil_chars = Array ( 0x00 ...0x20 ) - [ ?\n, ?\t, ?\s]
@@ -142,15 +142,15 @@ class HTML < Encoder
142
142
# \x9 (\t) and \xA (\n) not included
143
143
#HTML_ESCAPE_PATTERN = /[\t&"><\0-\x8\xB-\x1f\x7f-\xff]/
144
144
HTML_ESCAPE_PATTERN = /[\t "&><\0 -\x8 \xB -\x1f ]/
145
-
145
+
146
146
TOKEN_KIND_TO_INFO = Hash . new do |h , kind |
147
147
h [ kind ] = kind . to_s . gsub ( /_/ , ' ' ) . gsub ( /\b \w / ) { $&. capitalize }
148
148
end
149
-
149
+
150
150
TRANSPARENT_TOKEN_KINDS = Set [
151
151
:delimiter , :modifier , :content , :escape , :inline_delimiter ,
152
152
]
153
-
153
+
154
154
# Generate a hint about the given +kinds+ in a +hint+ style.
155
155
#
156
156
# +hint+ may be :info, :info_long or :debug.
@@ -168,32 +168,33 @@ def self.token_path_to_hint hint, kinds
168
168
end
169
169
title ? " title=\" #{ title } \" " : ''
170
170
end
171
-
171
+
172
172
def setup options
173
173
super
174
-
174
+
175
+ @line_number = 1
175
176
if options [ :wrap ] || options [ :line_numbers ]
176
177
@real_out = @out
177
178
@out = ''
178
179
end
179
-
180
+
180
181
options [ :break_lines ] = true if options [ :line_numbers ] == :inline
181
-
182
+
182
183
@break_lines = ( options [ :break_lines ] == true )
183
-
184
+
184
185
@HTML_ESCAPE = HTML_ESCAPE . dup
185
186
@HTML_ESCAPE [ "\t " ] = ' ' * options [ :tab_width ]
186
-
187
+
187
188
@opened = [ ]
188
189
@last_opened = nil
189
190
@css = CSS . new options [ :style ]
190
-
191
+
191
192
hint = options [ :hint ]
192
193
if hint && ![ :debug , :info , :info_long ] . include? ( hint )
193
194
raise ArgumentError , "Unknown value %p for :hint; \
194
195
expected :info, :info_long, :debug, false, or nil." % hint
195
196
end
196
-
197
+
197
198
css_classes = TokenKinds
198
199
case options [ :css ]
199
200
when :class
@@ -225,42 +226,42 @@ def setup options
225
226
else
226
227
raise ArgumentError , "Unknown value %p for :css." % options [ :css ]
227
228
end
228
-
229
+
229
230
@set_last_opened = options [ :hint ] || options [ :css ] == :style
230
231
end
231
-
232
+
232
233
def finish options
233
234
unless @opened . empty?
234
235
warn '%d tokens still open: %p' % [ @opened . size , @opened ] if $CODERAY_DEBUG
235
236
@out << '</span>' while @opened . pop
236
237
@last_opened = nil
237
238
end
238
-
239
+
239
240
@out . extend Output
240
241
@out . css = @css
241
242
if options [ :line_numbers ]
242
243
Numbering . number! @out , options [ :line_numbers ] , options
243
244
end
244
245
@out . wrap! options [ :wrap ]
245
246
@out . apply_title! options [ :title ]
246
-
247
+
247
248
if defined? ( @real_out ) && @real_out
248
249
@real_out << @out
249
250
@out = @real_out
250
251
end
251
-
252
+
252
253
super
253
254
end
254
-
255
+
255
256
public
256
-
257
+
257
258
def text_token text , kind
258
259
if text =~ /#{ HTML_ESCAPE_PATTERN } /o
259
260
text = text . gsub ( /#{ HTML_ESCAPE_PATTERN } /o ) { |m | @HTML_ESCAPE [ m ] }
260
261
end
261
-
262
+
262
263
style = @span_for_kind [ @last_opened ? [ kind , *@opened ] : kind ]
263
-
264
+
264
265
if @break_lines && ( i = text . index ( "\n " ) ) && ( c = @opened . size + ( style ? 1 : 0 ) ) > 0
265
266
close = '</span>' * c
266
267
reopen = ''
@@ -269,21 +270,21 @@ def text_token text, kind
269
270
end
270
271
text [ i .. -1 ] = text [ i .. -1 ] . gsub ( "\n " , "#{ close } \n #{ reopen } #{ style } " )
271
272
end
272
-
273
+
273
274
if style
274
275
@out << style << text << '</span>'
275
276
else
276
277
@out << text
277
278
end
278
279
end
279
-
280
+
280
281
# token groups, eg. strings
281
282
def begin_group kind
282
283
@out << ( @span_for_kind [ @last_opened ? [ kind , *@opened ] : kind ] || '<span>' )
283
284
@opened << kind
284
285
@last_opened = kind if @set_last_opened
285
286
end
286
-
287
+
287
288
def end_group kind
288
289
if $CODERAY_DEBUG && ( @opened . empty? || @opened . last != kind )
289
290
warn 'Malformed token stream: Trying to close a token (%p) ' \
@@ -294,9 +295,12 @@ def end_group kind
294
295
@last_opened = @opened . last if @last_opened
295
296
end
296
297
end
297
-
298
+
298
299
# whole lines to be highlighted, eg. a deleted line in a diff
299
300
def begin_line kind
301
+ @out << '<div class="line'
302
+ @out << ' odd' if @line_number . odd?
303
+ @out << '">'
300
304
if style = @span_for_kind [ @last_opened ? [ kind , *@opened ] : kind ]
301
305
if style [ 'class="' ]
302
306
@out << style . sub ( 'class="' , 'class="line ' )
@@ -309,7 +313,7 @@ def begin_line kind
309
313
@opened << kind
310
314
@last_opened = kind if @options [ :css ] == :style
311
315
end
312
-
316
+
313
317
def end_line kind
314
318
if $CODERAY_DEBUG && ( @opened . empty? || @opened . last != kind )
315
319
warn 'Malformed token stream: Trying to close a line (%p) ' \
@@ -319,9 +323,11 @@ def end_line kind
319
323
@out << '</span>'
320
324
@last_opened = @opened . last if @last_opened
321
325
end
326
+ @out << '</div>'
327
+ @line_number += 1
322
328
end
323
-
329
+
324
330
end
325
-
331
+
326
332
end
327
333
end
0 commit comments