summaryrefslogtreecommitdiff
path: root/lib/coderay/scanners/rhtml.rb
blob: 3b1817ebb1726bbee24971acfbdbc163d47f1cbf (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
module CodeRay
module Scanners

	load :html
	load :ruby

	# RHTML Scanner
	# 
	# $Id$
	class RHTML < Scanner

		include Streamable
		register_for :rhtml

		ERB_RUBY_BLOCK = /
			<%(?!%)[=-]?
			(?>
				[^%]*
				(?> %(?!>) [^%]* )* 
			)
			(?: %> )?
		/x

		START_OF_ERB = /
			<%(?!%)
		/x		

	private
		
		def setup
			@ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true
			@html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true
		end
		
		def scan_tokens tokens, options
			
			until eos?

				if (match = scan_until(/(?=#{START_OF_ERB})/o) || scan_until(/\z/)) and not match.empty?
					@html_scanner.tokenize match
					
				elsif match = scan(/#{ERB_RUBY_BLOCK}/o)
					start_tag = match[/\A<%[-=]?/]
					end_tag = match[/%?>?\z/]
					tokens << [:open, :inline]
					tokens << [start_tag, :delimiter]
					code = match[start_tag.size .. -1 - end_tag.size]
					@ruby_scanner.tokenize code
					tokens << [end_tag, :delimiter] unless end_tag.empty?
					tokens << [:close, :inline]

				else
					raise_inspect 'else-case reached!', tokens
				end

			end

			tokens

		end

	end

end
end