coderay 0.9.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. data/{lib/README → README_INDEX.rdoc} +10 -21
  2. data/Rakefile +6 -6
  3. data/bin/coderay +193 -64
  4. data/lib/coderay.rb +61 -105
  5. data/lib/coderay/duo.rb +17 -21
  6. data/lib/coderay/encoder.rb +100 -112
  7. data/lib/coderay/encoders/_map.rb +12 -7
  8. data/lib/coderay/encoders/comment_filter.rb +12 -30
  9. data/lib/coderay/encoders/count.rb +29 -11
  10. data/lib/coderay/encoders/debug.rb +32 -20
  11. data/lib/coderay/encoders/div.rb +13 -9
  12. data/lib/coderay/encoders/filter.rb +34 -51
  13. data/lib/coderay/encoders/html.rb +155 -161
  14. data/lib/coderay/encoders/html/css.rb +4 -9
  15. data/lib/coderay/encoders/html/numbering.rb +115 -0
  16. data/lib/coderay/encoders/html/output.rb +22 -70
  17. data/lib/coderay/encoders/json.rb +59 -45
  18. data/lib/coderay/encoders/lines_of_code.rb +12 -57
  19. data/lib/coderay/encoders/null.rb +6 -14
  20. data/lib/coderay/encoders/page.rb +13 -9
  21. data/lib/coderay/encoders/span.rb +13 -9
  22. data/lib/coderay/encoders/statistic.rb +58 -39
  23. data/lib/coderay/encoders/terminal.rb +179 -0
  24. data/lib/coderay/encoders/text.rb +31 -17
  25. data/lib/coderay/encoders/token_kind_filter.rb +111 -0
  26. data/lib/coderay/encoders/xml.rb +19 -18
  27. data/lib/coderay/encoders/yaml.rb +37 -9
  28. data/lib/coderay/for_redcloth.rb +4 -4
  29. data/lib/coderay/helpers/file_type.rb +127 -246
  30. data/lib/coderay/helpers/gzip.rb +41 -0
  31. data/lib/coderay/helpers/plugin.rb +241 -306
  32. data/lib/coderay/helpers/word_list.rb +65 -126
  33. data/lib/coderay/scanner.rb +173 -156
  34. data/lib/coderay/scanners/_map.rb +18 -17
  35. data/lib/coderay/scanners/c.rb +63 -77
  36. data/lib/coderay/scanners/clojure.rb +217 -0
  37. data/lib/coderay/scanners/cpp.rb +71 -84
  38. data/lib/coderay/scanners/css.rb +103 -120
  39. data/lib/coderay/scanners/debug.rb +47 -44
  40. data/lib/coderay/scanners/delphi.rb +70 -76
  41. data/lib/coderay/scanners/diff.rb +141 -50
  42. data/lib/coderay/scanners/erb.rb +81 -0
  43. data/lib/coderay/scanners/groovy.rb +104 -113
  44. data/lib/coderay/scanners/haml.rb +168 -0
  45. data/lib/coderay/scanners/html.rb +181 -110
  46. data/lib/coderay/scanners/java.rb +73 -75
  47. data/lib/coderay/scanners/java/builtin_types.rb +2 -0
  48. data/lib/coderay/scanners/java_script.rb +90 -101
  49. data/lib/coderay/scanners/json.rb +40 -53
  50. data/lib/coderay/scanners/php.rb +123 -147
  51. data/lib/coderay/scanners/python.rb +93 -91
  52. data/lib/coderay/scanners/raydebug.rb +66 -0
  53. data/lib/coderay/scanners/ruby.rb +343 -326
  54. data/lib/coderay/scanners/ruby/patterns.rb +40 -106
  55. data/lib/coderay/scanners/ruby/string_state.rb +71 -0
  56. data/lib/coderay/scanners/sql.rb +80 -66
  57. data/lib/coderay/scanners/text.rb +26 -0
  58. data/lib/coderay/scanners/xml.rb +1 -1
  59. data/lib/coderay/scanners/yaml.rb +74 -73
  60. data/lib/coderay/style.rb +10 -7
  61. data/lib/coderay/styles/_map.rb +3 -3
  62. data/lib/coderay/styles/alpha.rb +143 -0
  63. data/lib/coderay/token_kinds.rb +90 -0
  64. data/lib/coderay/tokens.rb +102 -277
  65. data/lib/coderay/tokens_proxy.rb +55 -0
  66. data/lib/coderay/version.rb +3 -0
  67. data/test/functional/basic.rb +200 -18
  68. data/test/functional/examples.rb +130 -0
  69. data/test/functional/for_redcloth.rb +15 -8
  70. data/test/functional/suite.rb +9 -6
  71. metadata +103 -123
  72. data/FOLDERS +0 -53
  73. data/bin/coderay_stylesheet +0 -4
  74. data/lib/coderay/encoders/html/numerization.rb +0 -133
  75. data/lib/coderay/encoders/term.rb +0 -158
  76. data/lib/coderay/encoders/token_class_filter.rb +0 -84
  77. data/lib/coderay/helpers/gzip_simple.rb +0 -123
  78. data/lib/coderay/scanners/nitro_xhtml.rb +0 -136
  79. data/lib/coderay/scanners/plaintext.rb +0 -20
  80. data/lib/coderay/scanners/rhtml.rb +0 -78
  81. data/lib/coderay/scanners/scheme.rb +0 -145
  82. data/lib/coderay/styles/cycnus.rb +0 -152
  83. data/lib/coderay/styles/murphy.rb +0 -134
  84. data/lib/coderay/token_classes.rb +0 -86
  85. data/test/functional/load_plugin_scanner.rb +0 -11
  86. data/test/functional/vhdl.rb +0 -126
  87. data/test/functional/word_list.rb +0 -79
@@ -1,21 +1,39 @@
1
1
  module CodeRay
2
2
  module Encoders
3
-
3
+
4
+ # Returns the number of tokens.
5
+ #
6
+ # Text and block tokens are counted.
4
7
  class Count < Encoder
5
-
6
- include Streamable
8
+
7
9
  register_for :count
8
-
9
- protected
10
-
10
+
11
+ protected
12
+
11
13
  def setup options
12
- @out = 0
14
+ super
15
+
16
+ @count = 0
13
17
  end
14
-
15
- def token text, kind
16
- @out += 1
18
+
19
+ def finish options
20
+ output @count
17
21
  end
22
+
23
+ public
24
+
25
+ def text_token text, kind
26
+ @count += 1
27
+ end
28
+
29
+ def begin_group kind
30
+ @count += 1
31
+ end
32
+ alias end_group begin_group
33
+ alias begin_line begin_group
34
+ alias end_line begin_group
35
+
18
36
  end
19
-
37
+
20
38
  end
21
39
  end
@@ -1,6 +1,6 @@
1
1
  module CodeRay
2
2
  module Encoders
3
-
3
+
4
4
  # = Debug Encoder
5
5
  #
6
6
  # Fast encoder producing simple debug output.
@@ -10,40 +10,52 @@ module Encoders
10
10
  # You cannot fully restore the tokens information from the
11
11
  # output, because consecutive :space tokens are merged.
12
12
  # Use Tokens#dump for caching purposes.
13
+ #
14
+ # See also: Scanners::Debug
13
15
  class Debug < Encoder
14
-
15
- include Streamable
16
+
16
17
  register_for :debug
17
-
18
+
18
19
  FILE_EXTENSION = 'raydebug'
19
-
20
- protected
20
+
21
+ def initialize options = {}
22
+ super
23
+ @opened = []
24
+ end
25
+
21
26
  def text_token text, kind
22
27
  if kind == :space
23
- text
28
+ @out << text
24
29
  else
30
+ # TODO: Escape (
25
31
  text = text.gsub(/[)\\]/, '\\\\\0') # escape ) and \
26
- "#{kind}(#{text})"
32
+ @out << kind.to_s << '(' << text << ')'
27
33
  end
28
34
  end
29
-
30
- def open_token kind
31
- "#{kind}<"
35
+
36
+ def begin_group kind
37
+ @opened << kind
38
+ @out << kind.to_s << '<'
32
39
  end
33
-
34
- def close_token kind
35
- ">"
40
+
41
+ def end_group kind
42
+ if @opened.last != kind
43
+ puts @out
44
+ raise "we are inside #{@opened.inspect}, not #{kind}"
45
+ end
46
+ @opened.pop
47
+ @out << '>'
36
48
  end
37
-
49
+
38
50
  def begin_line kind
39
- "#{kind}["
51
+ @out << kind.to_s << '['
40
52
  end
41
-
53
+
42
54
  def end_line kind
43
- "]"
55
+ @out << ']'
44
56
  end
45
-
57
+
46
58
  end
47
-
59
+
48
60
  end
49
61
  end
@@ -1,19 +1,23 @@
1
1
  module CodeRay
2
2
  module Encoders
3
-
3
+
4
4
  load :html
5
-
5
+
6
+ # Wraps HTML output into a DIV element, using inline styles by default.
7
+ #
8
+ # See Encoders::HTML for available options.
6
9
  class Div < HTML
7
-
10
+
8
11
  FILE_EXTENSION = 'div.html'
9
-
12
+
10
13
  register_for :div
11
-
14
+
12
15
  DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge \
13
- :css => :style,
14
- :wrap => :div
15
-
16
+ :css => :style,
17
+ :wrap => :div,
18
+ :line_numbers => false
19
+
16
20
  end
17
-
21
+
18
22
  end
19
23
  end
@@ -1,75 +1,58 @@
1
- ($:.unshift '../..'; require 'coderay') unless defined? CodeRay
2
1
  module CodeRay
3
2
  module Encoders
4
3
 
4
+ # A Filter encoder has another Tokens instance as output.
5
+ # It can be subclass to select, remove, or modify tokens in the stream.
6
+ #
7
+ # Subclasses of Filter are called "Filters" and can be chained.
8
+ #
9
+ # == Options
10
+ #
11
+ # === :tokens
12
+ #
13
+ # The Tokens object which will receive the output.
14
+ #
15
+ # Default: Tokens.new
16
+ #
17
+ # See also: TokenKindFilter
5
18
  class Filter < Encoder
6
19
 
7
20
  register_for :filter
8
21
 
9
22
  protected
10
23
  def setup options
11
- @out = Tokens.new
24
+ super
25
+
26
+ @tokens = options[:tokens] || Tokens.new
12
27
  end
13
28
 
14
- def text_token text, kind
15
- [text, kind] if include_text_token? text, kind
29
+ def finish options
30
+ output @tokens
16
31
  end
17
32
 
18
- def include_text_token? text, kind
19
- true
20
- end
33
+ public
21
34
 
22
- def block_token action, kind
23
- [action, kind] if include_block_token? action, kind
35
+ def text_token text, kind # :nodoc:
36
+ @tokens.text_token text, kind
24
37
  end
25
38
 
26
- def include_block_token? action, kind
27
- true
39
+ def begin_group kind # :nodoc:
40
+ @tokens.begin_group kind
28
41
  end
29
42
 
30
- end
31
-
32
- end
33
- end
34
-
35
- if $0 == __FILE__
36
- $VERBOSE = true
37
- $: << File.join(File.dirname(__FILE__), '..')
38
- eval DATA.read, nil, $0, __LINE__ + 4
39
- end
40
-
41
- __END__
42
- require 'test/unit'
43
-
44
- class FilterTest < Test::Unit::TestCase
45
-
46
- def test_creation
47
- assert CodeRay::Encoders::Filter < CodeRay::Encoders::Encoder
48
- filter = nil
49
- assert_nothing_raised do
50
- filter = CodeRay.encoder :filter
43
+ def begin_line kind # :nodoc:
44
+ @tokens.begin_line kind
51
45
  end
52
- assert_kind_of CodeRay::Encoders::Encoder, filter
53
- end
54
-
55
- def test_filtering_text_tokens
56
- tokens = CodeRay::Tokens.new
57
- 10.times do |i|
58
- tokens << [i.to_s, :index]
46
+
47
+ def end_group kind # :nodoc:
48
+ @tokens.end_group kind
59
49
  end
60
- assert_equal tokens, CodeRay::Encoders::Filter.new.encode_tokens(tokens)
61
- assert_equal tokens, tokens.filter
62
- end
63
-
64
- def test_filtering_block_tokens
65
- tokens = CodeRay::Tokens.new
66
- 10.times do |i|
67
- tokens << [:open, :index]
68
- tokens << [i.to_s, :content]
69
- tokens << [:close, :index]
50
+
51
+ def end_line kind # :nodoc:
52
+ @tokens.end_line kind
70
53
  end
71
- assert_equal tokens, CodeRay::Encoders::Filter.new.encode_tokens(tokens)
72
- assert_equal tokens, tokens.filter
54
+
73
55
  end
74
56
 
75
57
  end
58
+ end
@@ -2,7 +2,7 @@ require 'set'
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:
@@ -21,12 +21,12 @@ module Encoders
21
21
  # :line_numbers => :inline,
22
22
  # :css => :style
23
23
  # )
24
- # #-> <span class="no">1</span> <span style="color:#036; font-weight:bold;">Some</span> code
25
24
  #
26
25
  # == Options
27
26
  #
28
27
  # === :tab_width
29
28
  # Convert \t characters to +n+ spaces (a number.)
29
+ #
30
30
  # Default: 8
31
31
  #
32
32
  # === :css
@@ -48,10 +48,18 @@ module Encoders
48
48
  # Default: 'CodeRay output'
49
49
  #
50
50
  # === :line_numbers
51
- # Include line numbers in :table, :inline, :list or nil (no line numbers)
51
+ # Include line numbers in :table, :inline, or nil (no line numbers)
52
52
  #
53
53
  # Default: nil
54
54
  #
55
+ # === :line_number_anchors
56
+ # Adds anchors and links to the line numbers. Can be false (off), true (on),
57
+ # or a prefix string that will be prepended to the anchor name.
58
+ #
59
+ # The prefix must consist only of letters, digits, and underscores.
60
+ #
61
+ # Default: true, default prefix name: "line"
62
+ #
55
63
  # === :line_number_start
56
64
  # Where to start with line number counting.
57
65
  #
@@ -74,47 +82,48 @@ module Encoders
74
82
  #
75
83
  # === :hint
76
84
  # Include some information into the output using the title attribute.
77
- # Can be :info (show token type on mouse-over), :info_long (with full path)
85
+ # Can be :info (show token kind on mouse-over), :info_long (with full path)
78
86
  # or :debug (via inspect).
79
87
  #
80
88
  # Default: false
81
89
  class HTML < Encoder
82
-
83
- include Streamable
90
+
84
91
  register_for :html
85
-
86
- FILE_EXTENSION = 'html'
87
-
92
+
93
+ FILE_EXTENSION = 'snippet.html'
94
+
88
95
  DEFAULT_OPTIONS = {
89
96
  :tab_width => 8,
90
-
91
- :css => :class,
92
-
93
- :style => :cycnus,
94
- :wrap => nil,
97
+
98
+ :css => :class,
99
+ :style => :alpha,
100
+ :wrap => nil,
95
101
  :title => 'CodeRay output',
96
-
97
- :line_numbers => nil,
98
- :line_number_start => 1,
99
- :bold_every => 10,
100
- :highlight_lines => nil,
101
-
102
+
103
+ :line_numbers => nil,
104
+ :line_number_anchors => 'n',
105
+ :line_number_start => 1,
106
+ :bold_every => 10,
107
+ :highlight_lines => nil,
108
+
102
109
  :hint => false,
103
110
  }
104
-
105
- helper :output, :css
106
-
111
+
112
+ autoload :Output, 'coderay/encoders/html/output'
113
+ autoload :CSS, 'coderay/encoders/html/css'
114
+ autoload :Numbering, 'coderay/encoders/html/numbering'
115
+
107
116
  attr_reader :css
108
-
117
+
109
118
  protected
110
-
119
+
111
120
  HTML_ESCAPE = { #:nodoc:
112
121
  '&' => '&amp;',
113
122
  '"' => '&quot;',
114
123
  '>' => '&gt;',
115
124
  '<' => '&lt;',
116
125
  }
117
-
126
+
118
127
  # This was to prevent illegal HTML.
119
128
  # Strange chars should still be avoided in codes.
120
129
  evil_chars = Array(0x00...0x20) - [?\n, ?\t, ?\s]
@@ -124,185 +133,170 @@ module Encoders
124
133
  # \x9 (\t) and \xA (\n) not included
125
134
  #HTML_ESCAPE_PATTERN = /[\t&"><\0-\x8\xB-\x1f\x7f-\xff]/
126
135
  HTML_ESCAPE_PATTERN = /[\t"&><\0-\x8\xB-\x1f]/
127
-
128
- TOKEN_KIND_TO_INFO = Hash.new { |h, kind|
129
- h[kind] =
130
- case kind
131
- when :pre_constant
132
- 'Predefined constant'
133
- else
134
- kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize }
135
- end
136
- }
137
-
138
- TRANSPARENT_TOKEN_KINDS = [
136
+
137
+ TOKEN_KIND_TO_INFO = Hash.new do |h, kind|
138
+ h[kind] = kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize }
139
+ end
140
+
141
+ TRANSPARENT_TOKEN_KINDS = Set[
139
142
  :delimiter, :modifier, :content, :escape, :inline_delimiter,
140
- ].to_set
141
-
142
- # Generate a hint about the given +classes+ in a +hint+ style.
143
+ ]
144
+
145
+ # Generate a hint about the given +kinds+ in a +hint+ style.
143
146
  #
144
147
  # +hint+ may be :info, :info_long or :debug.
145
- def self.token_path_to_hint hint, classes
148
+ def self.token_path_to_hint hint, kinds
149
+ kinds = Array kinds
146
150
  title =
147
151
  case hint
148
152
  when :info
149
- TOKEN_KIND_TO_INFO[classes.first]
153
+ kinds = kinds[1..-1] if TRANSPARENT_TOKEN_KINDS.include? kinds.first
154
+ TOKEN_KIND_TO_INFO[kinds.first]
150
155
  when :info_long
151
- classes.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/')
156
+ kinds.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/')
152
157
  when :debug
153
- classes.inspect
158
+ kinds.inspect
154
159
  end
155
160
  title ? " title=\"#{title}\"" : ''
156
161
  end
157
-
162
+
158
163
  def setup options
159
164
  super
160
-
165
+
166
+ if options[:wrap] || options[:line_numbers]
167
+ @real_out = @out
168
+ @out = ''
169
+ end
170
+
161
171
  @HTML_ESCAPE = HTML_ESCAPE.dup
162
172
  @HTML_ESCAPE["\t"] = ' ' * options[:tab_width]
163
-
164
- @opened = [nil]
173
+
174
+ @opened = []
175
+ @last_opened = nil
165
176
  @css = CSS.new options[:style]
166
-
177
+
167
178
  hint = options[:hint]
168
- if hint and not [:debug, :info, :info_long].include? hint
179
+ if hint && ![:debug, :info, :info_long].include?(hint)
169
180
  raise ArgumentError, "Unknown value %p for :hint; \
170
- expected :info, :debug, false, or nil." % hint
181
+ expected :info, :info_long, :debug, false, or nil." % hint
171
182
  end
172
-
183
+
184
+ css_classes = TokenKinds
173
185
  case options[:css]
174
-
175
186
  when :class
176
- @css_style = Hash.new do |h, k|
177
- c = CodeRay::Tokens::ClassOfKind[k.first]
178
- if c == :NO_HIGHLIGHT and not hint
179
- h[k.dup] = false
180
- else
181
- title = if hint
182
- HTML.token_path_to_hint(hint, k[1..-1] << k.first)
183
- else
184
- ''
185
- end
186
- if c == :NO_HIGHLIGHT
187
- h[k.dup] = '<span%s>' % [title]
188
- else
189
- h[k.dup] = '<span%s class="%s">' % [title, c]
190
- end
191
- end
192
- end
193
-
194
- when :style
195
- @css_style = Hash.new do |h, k|
196
- if k.is_a? ::Array
197
- styles = k.dup
187
+ @span_for_kind = Hash.new do |h, k|
188
+ if k.is_a? ::Symbol
189
+ kind = k_dup = k
198
190
  else
199
- styles = [k]
191
+ kind = k.first
192
+ k_dup = k.dup
200
193
  end
201
- classes = styles.map { |c| Tokens::ClassOfKind[c] }
202
- if classes.first == :NO_HIGHLIGHT and not hint
203
- h[k] = false
194
+ if kind != :space && (hint || css_class = css_classes[kind])
195
+ title = HTML.token_path_to_hint hint, k if hint
196
+ css_class ||= css_classes[kind]
197
+ h[k_dup] = "<span#{title}#{" class=\"#{css_class}\"" if css_class}>"
204
198
  else
205
- styles.shift if TRANSPARENT_TOKEN_KINDS.include? styles.first
206
- title = HTML.token_path_to_hint hint, styles
207
- style = @css[*classes]
208
- h[k] =
209
- if style
210
- '<span%s style="%s">' % [title, style]
211
- else
212
- false
213
- end
199
+ h[k_dup] = nil
214
200
  end
215
201
  end
216
-
202
+ when :style
203
+ @span_for_kind = Hash.new do |h, k|
204
+ kind = k.is_a?(Symbol) ? k : k.first
205
+ h[k.is_a?(Symbol) ? k : k.dup] =
206
+ if kind != :space && (hint || css_classes[kind])
207
+ title = HTML.token_path_to_hint hint, k if hint
208
+ style = @css.get_style Array(k).map { |c| css_classes[c] }
209
+ "<span#{title}#{" style=\"#{style}\"" if style}>"
210
+ end
211
+ end
217
212
  else
218
213
  raise ArgumentError, "Unknown value %p for :css." % options[:css]
219
-
220
214
  end
215
+
216
+ @set_last_opened = options[:hint] || options[:css] == :style
221
217
  end
222
-
218
+
223
219
  def finish options
224
- @opened.shift
225
- @out << '</span>' * @opened.size
226
220
  unless @opened.empty?
227
- warn '%d tokens still open: %p' % [@opened.size, @opened]
221
+ warn '%d tokens still open: %p' % [@opened.size, @opened] if $CODERAY_DEBUG
222
+ @out << '</span>' while @opened.pop
223
+ @last_opened = nil
228
224
  end
229
-
225
+
230
226
  @out.extend Output
231
227
  @out.css = @css
232
- @out.numerize! options[:line_numbers], options
228
+ if options[:line_numbers]
229
+ Numbering.number! @out, options[:line_numbers], options
230
+ end
233
231
  @out.wrap! options[:wrap]
234
232
  @out.apply_title! options[:title]
235
-
236
- super
237
- end
238
-
239
- def token text, type = :plain
240
- case text
241
233
 
242
- when nil
243
- # raise 'Token with nil as text was given: %p' % [[text, type]]
244
-
245
- when String
246
- if text =~ /#{HTML_ESCAPE_PATTERN}/o
247
- text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] }
248
- end
249
- @opened[0] = type
250
- if text != "\n" && style = @css_style[@opened]
251
- @out << style << text << '</span>'
252
- else
253
- @out << text
254
- end
255
-
256
-
257
- # token groups, eg. strings
258
- when :open
259
- @opened[0] = type
260
- @out << (@css_style[@opened] || '<span>')
261
- @opened << type
262
- when :close
263
- if @opened.empty?
264
- # nothing to close
265
- else
266
- if $CODERAY_DEBUG and (@opened.size == 1 or @opened.last != type)
267
- raise 'Malformed token stream: Trying to close a token (%p) \
268
- that is not open. Open are: %p.' % [type, @opened[1..-1]]
269
- end
270
- @out << '</span>'
271
- @opened.pop
272
- end
234
+ if defined?(@real_out) && @real_out
235
+ @real_out << @out
236
+ @out = @real_out
237
+ end
273
238
 
274
- # whole lines to be highlighted, eg. a deleted line in a diff
275
- when :begin_line
276
- @opened[0] = type
277
- if style = @css_style[@opened]
278
- if style['class="']
279
- @out << style.sub('class="', 'class="line ')
280
- else
281
- @out << style.sub('>', ' class="line">')
282
- end
283
- else
284
- @out << '<span class="line">'
285
- end
286
- @opened << type
287
- when :end_line
288
- if @opened.empty?
289
- # nothing to close
239
+ super
240
+ end
241
+
242
+ public
243
+
244
+ def text_token text, kind
245
+ if text =~ /#{HTML_ESCAPE_PATTERN}/o
246
+ text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] }
247
+ end
248
+ if style = @span_for_kind[@last_opened ? [kind, *@opened] : kind]
249
+ @out << style << text << '</span>'
250
+ else
251
+ @out << text
252
+ end
253
+ end
254
+
255
+ # token groups, eg. strings
256
+ def begin_group kind
257
+ @out << (@span_for_kind[@last_opened ? [kind, *@opened] : kind] || '<span>')
258
+ @opened << kind
259
+ @last_opened = kind if @set_last_opened
260
+ end
261
+
262
+ def end_group kind
263
+ if $CODERAY_DEBUG && (@opened.empty? || @opened.last != kind)
264
+ warn 'Malformed token stream: Trying to close a token (%p) ' \
265
+ 'that is not open. Open are: %p.' % [kind, @opened[1..-1]]
266
+ end
267
+ if @opened.pop
268
+ @out << '</span>'
269
+ @last_opened = @opened.last if @last_opened
270
+ end
271
+ end
272
+
273
+ # whole lines to be highlighted, eg. a deleted line in a diff
274
+ def begin_line kind
275
+ if style = @span_for_kind[@last_opened ? [kind, *@opened] : kind]
276
+ if style['class="']
277
+ @out << style.sub('class="', 'class="line ')
290
278
  else
291
- if $CODERAY_DEBUG and (@opened.size == 1 or @opened.last != type)
292
- raise 'Malformed token stream: Trying to close a line (%p) \
293
- that is not open. Open are: %p.' % [type, @opened[1..-1]]
294
- end
295
- @out << '</span>'
296
- @opened.pop
279
+ @out << style.sub('>', ' class="line">')
297
280
  end
298
-
299
281
  else
300
- raise 'unknown token kind: %p' % [text]
301
-
282
+ @out << '<span class="line">'
302
283
  end
284
+ @opened << kind
285
+ @last_opened = kind if @options[:css] == :style
303
286
  end
304
-
287
+
288
+ def end_line kind
289
+ if $CODERAY_DEBUG && (@opened.empty? || @opened.last != kind)
290
+ warn 'Malformed token stream: Trying to close a line (%p) ' \
291
+ 'that is not open. Open are: %p.' % [kind, @opened[1..-1]]
292
+ end
293
+ if @opened.pop
294
+ @out << '</span>'
295
+ @last_opened = @opened.last if @last_opened
296
+ end
297
+ end
298
+
305
299
  end
306
-
300
+
307
301
  end
308
302
  end