Chris@909
|
1 module CodeRay
|
Chris@909
|
2 module Scanners
|
Chris@909
|
3
|
Chris@909
|
4 load :ruby
|
Chris@909
|
5 load :html
|
Chris@909
|
6 load :java_script
|
Chris@909
|
7
|
Chris@909
|
8 class HAML < Scanner
|
Chris@909
|
9
|
Chris@909
|
10 register_for :haml
|
Chris@909
|
11 title 'HAML Template'
|
Chris@909
|
12
|
Chris@909
|
13 KINDS_NOT_LOC = HTML::KINDS_NOT_LOC
|
Chris@909
|
14
|
Chris@909
|
15 protected
|
Chris@909
|
16
|
Chris@909
|
17 def setup
|
Chris@909
|
18 super
|
Chris@909
|
19 @ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true
|
Chris@909
|
20 @embedded_ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true, :state => @ruby_scanner.interpreted_string_state
|
Chris@909
|
21 @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true
|
Chris@909
|
22 end
|
Chris@909
|
23
|
Chris@909
|
24 def scan_tokens encoder, options
|
Chris@909
|
25
|
Chris@909
|
26 match = nil
|
Chris@909
|
27 code = ''
|
Chris@909
|
28
|
Chris@909
|
29 until eos?
|
Chris@909
|
30
|
Chris@909
|
31 if bol?
|
Chris@909
|
32 if match = scan(/!!!.*/)
|
Chris@909
|
33 encoder.text_token match, :doctype
|
Chris@909
|
34 next
|
Chris@909
|
35 end
|
Chris@909
|
36
|
Chris@909
|
37 if match = scan(/(?>( *)(\/(?!\[if)|-\#|:javascript|:ruby|:\w+) *)(?=\n)/)
|
Chris@909
|
38 encoder.text_token match, :comment
|
Chris@909
|
39
|
Chris@909
|
40 code = self[2]
|
Chris@909
|
41 if match = scan(/(?:\n+#{self[1]} .*)+/)
|
Chris@909
|
42 case code
|
Chris@909
|
43 when '/', '-#'
|
Chris@909
|
44 encoder.text_token match, :comment
|
Chris@909
|
45 when ':javascript'
|
Chris@909
|
46 # TODO: recognize #{...} snippets inside JavaScript
|
Chris@909
|
47 @java_script_scanner ||= CodeRay.scanner :java_script, :tokens => @tokens, :keep_tokens => true
|
Chris@909
|
48 @java_script_scanner.tokenize match, :tokens => encoder
|
Chris@909
|
49 when ':ruby'
|
Chris@909
|
50 @ruby_scanner.tokenize match, :tokens => encoder
|
Chris@909
|
51 when /:\w+/
|
Chris@909
|
52 encoder.text_token match, :comment
|
Chris@909
|
53 else
|
Chris@909
|
54 raise 'else-case reached: %p' % [code]
|
Chris@909
|
55 end
|
Chris@909
|
56 end
|
Chris@909
|
57 end
|
Chris@909
|
58
|
Chris@909
|
59 if match = scan(/ +/)
|
Chris@909
|
60 encoder.text_token match, :space
|
Chris@909
|
61 end
|
Chris@909
|
62
|
Chris@909
|
63 if match = scan(/\/.*/)
|
Chris@909
|
64 encoder.text_token match, :comment
|
Chris@909
|
65 next
|
Chris@909
|
66 end
|
Chris@909
|
67
|
Chris@909
|
68 if match = scan(/\\/)
|
Chris@909
|
69 encoder.text_token match, :plain
|
Chris@909
|
70 if match = scan(/.+/)
|
Chris@909
|
71 @html_scanner.tokenize match, :tokens => encoder
|
Chris@909
|
72 end
|
Chris@909
|
73 next
|
Chris@909
|
74 end
|
Chris@909
|
75
|
Chris@909
|
76 tag = false
|
Chris@909
|
77
|
Chris@909
|
78 if match = scan(/%[\w:]+\/?/)
|
Chris@909
|
79 encoder.text_token match, :tag
|
Chris@909
|
80 # if match = scan(/( +)(.+)/)
|
Chris@909
|
81 # encoder.text_token self[1], :space
|
Chris@909
|
82 # @embedded_ruby_scanner.tokenize self[2], :tokens => encoder
|
Chris@909
|
83 # end
|
Chris@909
|
84 tag = true
|
Chris@909
|
85 end
|
Chris@909
|
86
|
Chris@909
|
87 while match = scan(/([.#])[-\w]*\w/)
|
Chris@909
|
88 encoder.text_token match, self[1] == '#' ? :constant : :class
|
Chris@909
|
89 tag = true
|
Chris@909
|
90 end
|
Chris@909
|
91
|
Chris@909
|
92 if tag && match = scan(/(\()([^)]+)?(\))?/)
|
Chris@909
|
93 # TODO: recognize title=@title, class="widget_#{@widget.number}"
|
Chris@909
|
94 encoder.text_token self[1], :plain
|
Chris@909
|
95 @html_scanner.tokenize self[2], :tokens => encoder, :state => :attribute if self[2]
|
Chris@909
|
96 encoder.text_token self[3], :plain if self[3]
|
Chris@909
|
97 end
|
Chris@909
|
98
|
Chris@909
|
99 if tag && match = scan(/\{/)
|
Chris@909
|
100 encoder.text_token match, :plain
|
Chris@909
|
101
|
Chris@909
|
102 code = ''
|
Chris@909
|
103 level = 1
|
Chris@909
|
104 while true
|
Chris@909
|
105 code << scan(/([^\{\},\n]|, *\n?)*/)
|
Chris@909
|
106 case match = getch
|
Chris@909
|
107 when '{'
|
Chris@909
|
108 level += 1
|
Chris@909
|
109 code << match
|
Chris@909
|
110 when '}'
|
Chris@909
|
111 level -= 1
|
Chris@909
|
112 if level > 0
|
Chris@909
|
113 code << match
|
Chris@909
|
114 else
|
Chris@909
|
115 break
|
Chris@909
|
116 end
|
Chris@909
|
117 when "\n", ",", nil
|
Chris@909
|
118 break
|
Chris@909
|
119 end
|
Chris@909
|
120 end
|
Chris@909
|
121 @ruby_scanner.tokenize code, :tokens => encoder unless code.empty?
|
Chris@909
|
122
|
Chris@909
|
123 encoder.text_token match, :plain if match
|
Chris@909
|
124 end
|
Chris@909
|
125
|
Chris@909
|
126 if tag && match = scan(/(\[)([^\]\n]+)?(\])?/)
|
Chris@909
|
127 encoder.text_token self[1], :plain
|
Chris@909
|
128 @ruby_scanner.tokenize self[2], :tokens => encoder if self[2]
|
Chris@909
|
129 encoder.text_token self[3], :plain if self[3]
|
Chris@909
|
130 end
|
Chris@909
|
131
|
Chris@909
|
132 if tag && match = scan(/\//)
|
Chris@909
|
133 encoder.text_token match, :tag
|
Chris@909
|
134 end
|
Chris@909
|
135
|
Chris@909
|
136 if scan(/(>?<?[-=]|[&!]=|(& |!)|~)( *)([^,\n\|]+(?:(, *|\|(?=.|\n.*\|$))\n?[^,\n\|]*)*)?/)
|
Chris@909
|
137 encoder.text_token self[1] + self[3], :plain
|
Chris@909
|
138 if self[4]
|
Chris@909
|
139 if self[2]
|
Chris@909
|
140 @embedded_ruby_scanner.tokenize self[4], :tokens => encoder
|
Chris@909
|
141 else
|
Chris@909
|
142 @ruby_scanner.tokenize self[4], :tokens => encoder
|
Chris@909
|
143 end
|
Chris@909
|
144 end
|
Chris@909
|
145 elsif match = scan(/((?:<|><?)(?![!?\/\w]))?(.+)?/)
|
Chris@909
|
146 encoder.text_token self[1], :plain if self[1]
|
Chris@909
|
147 # TODO: recognize #{...} snippets
|
Chris@909
|
148 @html_scanner.tokenize self[2], :tokens => encoder if self[2]
|
Chris@909
|
149 end
|
Chris@909
|
150
|
Chris@909
|
151 elsif match = scan(/.+/)
|
Chris@909
|
152 @html_scanner.tokenize match, :tokens => encoder
|
Chris@909
|
153
|
Chris@909
|
154 end
|
Chris@909
|
155
|
Chris@909
|
156 if match = scan(/\n/)
|
Chris@909
|
157 encoder.text_token match, :space
|
Chris@909
|
158 end
|
Chris@909
|
159 end
|
Chris@909
|
160
|
Chris@909
|
161 encoder
|
Chris@909
|
162
|
Chris@909
|
163 end
|
Chris@909
|
164
|
Chris@909
|
165 end
|
Chris@909
|
166
|
Chris@909
|
167 end
|
Chris@909
|
168 end
|