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,16 +1,17 @@
1
1
  module CodeRay
2
2
  module Scanners
3
3
 
4
+ # Scanner for C++.
5
+ #
6
+ # Aliases: +cplusplus+, c++
4
7
  class CPlusPlus < Scanner
5
8
 
6
- include Streamable
7
-
8
9
  register_for :cpp
9
10
  file_extension 'cpp'
10
11
  title 'C++'
11
12
 
12
- # http://www.cppreference.com/wiki/keywords/start
13
- RESERVED_WORDS = [
13
+ #-- http://www.cppreference.com/wiki/keywords/start
14
+ KEYWORDS = [
14
15
  'and', 'and_eq', 'asm', 'bitand', 'bitor', 'break',
15
16
  'case', 'catch', 'class', 'compl', 'const_cast',
16
17
  'continue', 'default', 'delete', 'do', 'dynamic_cast', 'else',
@@ -18,37 +19,39 @@ module Scanners
18
19
  'not', 'not_eq', 'or', 'or_eq', 'reinterpret_cast', 'return',
19
20
  'sizeof', 'static_cast', 'struct', 'switch', 'template',
20
21
  'throw', 'try', 'typedef', 'typeid', 'typename', 'union',
21
- 'while', 'xor', 'xor_eq'
22
- ]
23
-
22
+ 'while', 'xor', 'xor_eq',
23
+ ] # :nodoc:
24
+
24
25
  PREDEFINED_TYPES = [
25
26
  'bool', 'char', 'double', 'float', 'int', 'long',
26
- 'short', 'signed', 'unsigned', 'wchar_t', 'string'
27
- ]
27
+ 'short', 'signed', 'unsigned', 'wchar_t', 'string',
28
+ ] # :nodoc:
28
29
  PREDEFINED_CONSTANTS = [
29
30
  'false', 'true',
30
31
  'EOF', 'NULL',
31
- ]
32
+ ] # :nodoc:
32
33
  PREDEFINED_VARIABLES = [
33
- 'this'
34
- ]
34
+ 'this',
35
+ ] # :nodoc:
35
36
  DIRECTIVES = [
36
37
  'auto', 'const', 'explicit', 'extern', 'friend', 'inline', 'mutable', 'operator',
37
38
  'private', 'protected', 'public', 'register', 'static', 'using', 'virtual', 'void',
38
- 'volatile'
39
- ]
40
-
39
+ 'volatile',
40
+ ] # :nodoc:
41
+
41
42
  IDENT_KIND = WordList.new(:ident).
42
- add(RESERVED_WORDS, :reserved).
43
- add(PREDEFINED_TYPES, :pre_type).
43
+ add(KEYWORDS, :keyword).
44
+ add(PREDEFINED_TYPES, :predefined_type).
44
45
  add(PREDEFINED_VARIABLES, :local_variable).
45
46
  add(DIRECTIVES, :directive).
46
- add(PREDEFINED_CONSTANTS, :pre_constant)
47
-
48
- ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x
49
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x
47
+ add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
50
48
 
51
- def scan_tokens tokens, options
49
+ ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
50
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
51
+
52
+ protected
53
+
54
+ def scan_tokens encoder, options
52
55
 
53
56
  state = :initial
54
57
  label_expected = true
@@ -58,9 +61,6 @@ module Scanners
58
61
 
59
62
  until eos?
60
63
 
61
- kind = nil
62
- match = nil
63
-
64
64
  case state
65
65
 
66
66
  when :initial
@@ -70,15 +70,14 @@ module Scanners
70
70
  in_preproc_line = false
71
71
  label_expected = label_expected_before_preproc_line
72
72
  end
73
- tokens << [match, :space]
74
- next
73
+ encoder.text_token match, :space
75
74
 
76
- elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
77
- kind = :comment
75
+ elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
76
+ encoder.text_token match, :comment
78
77
 
79
78
  elsif match = scan(/ \# \s* if \s* 0 /x)
80
79
  match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
81
- kind = :comment
80
+ encoder.text_token match, :comment
82
81
 
83
82
  elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x)
84
83
  label_expected = match =~ /[;\{\}]/
@@ -86,7 +85,7 @@ module Scanners
86
85
  label_expected = true if match == ':'
87
86
  case_expected = false
88
87
  end
89
- kind = :operator
88
+ encoder.text_token match, :operator
90
89
 
91
90
  elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
92
91
  kind = IDENT_KIND[match]
@@ -95,7 +94,7 @@ module Scanners
95
94
  match << matched
96
95
  else
97
96
  label_expected = false
98
- if kind == :reserved
97
+ if kind == :keyword
99
98
  case match
100
99
  when 'class'
101
100
  state = :class_name_expected
@@ -104,122 +103,110 @@ module Scanners
104
103
  end
105
104
  end
106
105
  end
106
+ encoder.text_token match, kind
107
107
 
108
- elsif scan(/\$/)
109
- kind = :ident
108
+ elsif match = scan(/\$/)
109
+ encoder.text_token match, :ident
110
110
 
111
111
  elsif match = scan(/L?"/)
112
- tokens << [:open, :string]
112
+ encoder.begin_group :string
113
113
  if match[0] == ?L
114
- tokens << ['L', :modifier]
114
+ encoder.text_token match, 'L', :modifier
115
115
  match = '"'
116
116
  end
117
117
  state = :string
118
- kind = :delimiter
118
+ encoder.text_token match, :delimiter
119
119
 
120
- elsif scan(/#[ \t]*(\w*)/)
121
- kind = :preprocessor
120
+ elsif match = scan(/#[ \t]*(\w*)/)
121
+ encoder.text_token match, :preprocessor
122
122
  in_preproc_line = true
123
123
  label_expected_before_preproc_line = label_expected
124
124
  state = :include_expected if self[1] == 'include'
125
125
 
126
- elsif scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
126
+ elsif match = scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
127
127
  label_expected = false
128
- kind = :char
128
+ encoder.text_token match, :char
129
129
 
130
- elsif scan(/0[xX][0-9A-Fa-f]+/)
130
+ elsif match = scan(/0[xX][0-9A-Fa-f]+/)
131
131
  label_expected = false
132
- kind = :hex
132
+ encoder.text_token match, :hex
133
133
 
134
- elsif scan(/(?:0[0-7]+)(?![89.eEfF])/)
134
+ elsif match = scan(/(?:0[0-7]+)(?![89.eEfF])/)
135
135
  label_expected = false
136
- kind = :oct
136
+ encoder.text_token match, :octal
137
137
 
138
- elsif scan(/(?:\d+)(?![.eEfF])L?L?/)
138
+ elsif match = scan(/(?:\d+)(?![.eEfF])L?L?/)
139
139
  label_expected = false
140
- kind = :integer
140
+ encoder.text_token match, :integer
141
141
 
142
- elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
142
+ elsif match = scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
143
143
  label_expected = false
144
- kind = :float
144
+ encoder.text_token match, :float
145
145
 
146
146
  else
147
- getch
148
- kind = :error
147
+ encoder.text_token getch, :error
149
148
 
150
149
  end
151
150
 
152
151
  when :string
153
- if scan(/[^\\"]+/)
154
- kind = :content
155
- elsif scan(/"/)
156
- tokens << ['"', :delimiter]
157
- tokens << [:close, :string]
152
+ if match = scan(/[^\\"]+/)
153
+ encoder.text_token match, :content
154
+ elsif match = scan(/"/)
155
+ encoder.text_token match, :delimiter
156
+ encoder.end_group :string
158
157
  state = :initial
159
158
  label_expected = false
160
- next
161
- elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
162
- kind = :char
163
- elsif scan(/ \\ | $ /x)
164
- tokens << [:close, :string]
165
- kind = :error
159
+ elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
160
+ encoder.text_token match, :char
161
+ elsif match = scan(/ \\ | $ /x)
162
+ encoder.end_group :string
163
+ encoder.text_token match, :error
166
164
  state = :initial
167
165
  label_expected = false
168
166
  else
169
- raise_inspect "else case \" reached; %p not handled." % peek(1), tokens
167
+ raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
170
168
  end
171
169
 
172
170
  when :include_expected
173
- if scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
174
- kind = :include
171
+ if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
172
+ encoder.text_token match, :include
175
173
  state = :initial
176
174
 
177
175
  elsif match = scan(/\s+/)
178
- kind = :space
176
+ encoder.text_token match, :space
179
177
  state = :initial if match.index ?\n
180
178
 
181
179
  else
182
180
  state = :initial
183
- next
184
181
 
185
182
  end
186
183
 
187
184
  when :class_name_expected
188
- if scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
189
- kind = :class
185
+ if match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
186
+ encoder.text_token match, :class
190
187
  state = :initial
191
188
 
192
189
  elsif match = scan(/\s+/)
193
- kind = :space
190
+ encoder.text_token match, :space
194
191
 
195
192
  else
196
- getch
197
- kind = :error
193
+ encoder.text_token getch, :error
198
194
  state = :initial
199
195
 
200
196
  end
201
197
 
202
198
  else
203
- raise_inspect 'Unknown state', tokens
199
+ raise_inspect 'Unknown state', encoder
204
200
 
205
201
  end
206
202
 
207
- match ||= matched
208
- if $CODERAY_DEBUG and not kind
209
- raise_inspect 'Error token %p in line %d' %
210
- [[match, kind], line], tokens
211
- end
212
- raise_inspect 'Empty token', tokens unless match
213
-
214
- tokens << [match, kind]
215
-
216
203
  end
217
204
 
218
205
  if state == :string
219
- tokens << [:close, :string]
206
+ encoder.end_group :string
220
207
  end
221
208
 
222
- tokens
209
+ encoder
223
210
  end
224
211
 
225
212
  end
@@ -2,208 +2,191 @@ module CodeRay
2
2
  module Scanners
3
3
 
4
4
  class CSS < Scanner
5
-
5
+
6
6
  register_for :css
7
-
7
+
8
8
  KINDS_NOT_LOC = [
9
9
  :comment,
10
10
  :class, :pseudo_class, :type,
11
11
  :constant, :directive,
12
- :key, :value, :operator, :color, :float, :content, :delimiter,
12
+ :key, :value, :operator, :color, :float, :string,
13
13
  :error, :important,
14
- ]
14
+ ] # :nodoc:
15
15
 
16
- module RE
16
+ module RE # :nodoc:
17
17
  Hex = /[0-9a-fA-F]/
18
18
  Unicode = /\\#{Hex}{1,6}(?:\r\n|\s)?/ # differs from standard because it allows uppercase hex too
19
19
  Escape = /#{Unicode}|\\[^\r\n\f0-9a-fA-F]/
20
20
  NMChar = /[-_a-zA-Z0-9]|#{Escape}/
21
21
  NMStart = /[_a-zA-Z]|#{Escape}/
22
22
  NL = /\r\n|\r|\n|\f/
23
- String1 = /"(?:[^\n\r\f\\"]|\\#{NL}|#{Escape})*"?/ # FIXME: buggy regexp
24
- String2 = /'(?:[^\n\r\f\\']|\\#{NL}|#{Escape})*'?/ # FIXME: buggy regexp
23
+ String1 = /"(?:[^\n\r\f\\"]|\\#{NL}|#{Escape})*"?/ # TODO: buggy regexp
24
+ String2 = /'(?:[^\n\r\f\\']|\\#{NL}|#{Escape})*'?/ # TODO: buggy regexp
25
25
  String = /#{String1}|#{String2}/
26
-
26
+
27
27
  HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/
28
28
  Color = /#{HexColor}/
29
-
29
+
30
30
  Num = /-?(?:[0-9]+|[0-9]*\.[0-9]+)/
31
31
  Name = /#{NMChar}+/
32
32
  Ident = /-?#{NMStart}#{NMChar}*/
33
33
  AtKeyword = /@#{Ident}/
34
34
  Percentage = /#{Num}%/
35
-
35
+
36
36
  reldimensions = %w[em ex px]
37
37
  absdimensions = %w[in cm mm pt pc]
38
38
  Unit = Regexp.union(*(reldimensions + absdimensions))
39
-
39
+
40
40
  Dimension = /#{Num}#{Unit}/
41
-
41
+
42
42
  Comment = %r! /\* (?: .*? \*/ | .* ) !mx
43
- Function = /(?:url|alpha)\((?:[^)\n\r\f]|\\\))*\)?/
44
-
43
+ Function = /(?:url|alpha|attr|counters?)\((?:[^)\n\r\f]|\\\))*\)?/
44
+
45
45
  Id = /##{Name}/
46
46
  Class = /\.#{Name}/
47
47
  PseudoClass = /:#{Name}/
48
48
  AttributeSelector = /\[[^\]]*\]?/
49
-
50
49
  end
51
-
52
- def scan_tokens tokens, options
50
+
51
+ protected
52
+
53
+ def scan_tokens encoder, options
53
54
 
54
55
  value_expected = nil
55
56
  states = [:initial]
56
-
57
+
57
58
  until eos?
58
-
59
- kind = nil
60
- match = nil
61
-
62
- if scan(/\s+/)
63
- kind = :space
64
-
59
+
60
+ if match = scan(/\s+/)
61
+ encoder.text_token match, :space
62
+
65
63
  elsif case states.last
66
64
  when :initial, :media
67
- if scan(/(?>#{RE::Ident})(?!\()|\*/ox)
68
- kind = :type
69
- elsif scan RE::Class
70
- kind = :class
71
- elsif scan RE::Id
72
- kind = :constant
73
- elsif scan RE::PseudoClass
74
- kind = :pseudo_class
65
+ if match = scan(/(?>#{RE::Ident})(?!\()|\*/ox)
66
+ encoder.text_token match, :type
67
+ next
68
+ elsif match = scan(RE::Class)
69
+ encoder.text_token match, :class
70
+ next
71
+ elsif match = scan(RE::Id)
72
+ encoder.text_token match, :constant
73
+ next
74
+ elsif match = scan(RE::PseudoClass)
75
+ encoder.text_token match, :pseudo_class
76
+ next
75
77
  elsif match = scan(RE::AttributeSelector)
76
78
  # TODO: Improve highlighting inside of attribute selectors.
77
- tokens << [:open, :string]
78
- tokens << [match[0,1], :delimiter]
79
- tokens << [match[1..-2], :content] if match.size > 2
80
- tokens << [match[-1,1], :delimiter] if match[-1] == ?]
81
- tokens << [:close, :string]
79
+ encoder.text_token match[0,1], :operator
80
+ encoder.text_token match[1..-2], :attribute_name if match.size > 2
81
+ encoder.text_token match[-1,1], :operator if match[-1] == ?]
82
82
  next
83
83
  elsif match = scan(/@media/)
84
- kind = :directive
84
+ encoder.text_token match, :directive
85
85
  states.push :media_before_name
86
+ next
86
87
  end
87
88
 
88
89
  when :block
89
- if scan(/(?>#{RE::Ident})(?!\()/ox)
90
+ if match = scan(/(?>#{RE::Ident})(?!\()/ox)
90
91
  if value_expected
91
- kind = :value
92
+ encoder.text_token match, :value
92
93
  else
93
- kind = :key
94
+ encoder.text_token match, :key
94
95
  end
96
+ next
95
97
  end
96
-
98
+
97
99
  when :media_before_name
98
- if scan RE::Ident
99
- kind = :type
100
+ if match = scan(RE::Ident)
101
+ encoder.text_token match, :type
100
102
  states[-1] = :media_after_name
103
+ next
101
104
  end
102
105
 
103
106
  when :media_after_name
104
- if scan(/\{/)
105
- kind = :operator
107
+ if match = scan(/\{/)
108
+ encoder.text_token match, :operator
106
109
  states[-1] = :media
110
+ next
107
111
  end
108
112
 
109
- when :comment
110
- if scan(/(?:[^*\s]|\*(?!\/))+/)
111
- kind = :comment
112
- elsif scan(/\*\//)
113
- kind = :comment
114
- states.pop
115
- elsif scan(/\s+/)
116
- kind = :space
117
- end
118
-
119
113
  else
120
- raise_inspect 'Unknown state', tokens
121
-
114
+ #:nocov:
115
+ raise_inspect 'Unknown state', encoder
116
+ #:nocov:
117
+
122
118
  end
123
-
124
- elsif scan(/\/\*/)
125
- kind = :comment
126
- states.push :comment
127
-
128
- elsif scan(/\{/)
119
+
120
+ elsif match = scan(/\/\*(?:.*?\*\/|\z)/m)
121
+ encoder.text_token match, :comment
122
+
123
+ elsif match = scan(/\{/)
129
124
  value_expected = false
130
- kind = :operator
125
+ encoder.text_token match, :operator
131
126
  states.push :block
132
-
133
- elsif scan(/\}/)
127
+
128
+ elsif match = scan(/\}/)
134
129
  value_expected = false
135
130
  if states.last == :block || states.last == :media
136
- kind = :operator
131
+ encoder.text_token match, :operator
137
132
  states.pop
138
133
  else
139
- kind = :error
134
+ encoder.text_token match, :error
140
135
  end
141
-
136
+
142
137
  elsif match = scan(/#{RE::String}/o)
143
- tokens << [:open, :string]
144
- tokens << [match[0, 1], :delimiter]
145
- tokens << [match[1..-2], :content] if match.size > 2
146
- tokens << [match[-1, 1], :delimiter] if match.size >= 2
147
- tokens << [:close, :string]
148
- next
149
-
138
+ encoder.begin_group :string
139
+ encoder.text_token match[0, 1], :delimiter
140
+ encoder.text_token match[1..-2], :content if match.size > 2
141
+ encoder.text_token match[-1, 1], :delimiter if match.size >= 2
142
+ encoder.end_group :string
143
+
150
144
  elsif match = scan(/#{RE::Function}/o)
151
- tokens << [:open, :string]
145
+ encoder.begin_group :string
152
146
  start = match[/^\w+\(/]
153
- tokens << [start, :delimiter]
147
+ encoder.text_token start, :delimiter
154
148
  if match[-1] == ?)
155
- tokens << [match[start.size..-2], :content]
156
- tokens << [')', :delimiter]
149
+ encoder.text_token match[start.size..-2], :content
150
+ encoder.text_token ')', :delimiter
157
151
  else
158
- tokens << [match[start.size..-1], :content]
152
+ encoder.text_token match[start.size..-1], :content
159
153
  end
160
- tokens << [:close, :string]
161
- next
162
-
163
- elsif scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox)
164
- kind = :float
165
-
166
- elsif scan(/#{RE::Color}/o)
167
- kind = :color
168
-
169
- elsif scan(/! *important/)
170
- kind = :important
171
-
172
- elsif scan(/rgb\([^()\n]*\)?/)
173
- kind = :color
174
-
175
- elsif scan(/#{RE::AtKeyword}/o)
176
- kind = :directive
177
-
154
+ encoder.end_group :string
155
+
156
+ elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox)
157
+ encoder.text_token match, :float
158
+
159
+ elsif match = scan(/#{RE::Color}/o)
160
+ encoder.text_token match, :color
161
+
162
+ elsif match = scan(/! *important/)
163
+ encoder.text_token match, :important
164
+
165
+ elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/)
166
+ encoder.text_token match, :color
167
+
168
+ elsif match = scan(RE::AtKeyword)
169
+ encoder.text_token match, :directive
170
+
178
171
  elsif match = scan(/ [+>:;,.=()\/] /x)
179
172
  if match == ':'
180
173
  value_expected = true
181
174
  elsif match == ';'
182
175
  value_expected = false
183
176
  end
184
- kind = :operator
185
-
177
+ encoder.text_token match, :operator
178
+
186
179
  else
187
- getch
188
- kind = :error
189
-
190
- end
191
-
192
- match ||= matched
193
- if $CODERAY_DEBUG and not kind
194
- raise_inspect 'Error token %p in line %d' %
195
- [[match, kind], line], tokens
180
+ encoder.text_token getch, :error
181
+
196
182
  end
197
- raise_inspect 'Empty token', tokens unless match
198
-
199
- tokens << [match, kind]
200
-
183
+
201
184
  end
202
-
203
- tokens
185
+
186
+ encoder
204
187
  end
205
-
188
+
206
189
  end
207
-
190
+
208
191
  end
209
192
  end