Chris@0
|
1 module CodeRay
|
Chris@0
|
2 module Scanners
|
Chris@0
|
3
|
Chris@0
|
4 load :html
|
Chris@0
|
5 load :ruby
|
Chris@0
|
6
|
Chris@0
|
7 # Nitro XHTML Scanner
|
Chris@0
|
8 class NitroXHTML < Scanner
|
Chris@0
|
9
|
Chris@0
|
10 include Streamable
|
Chris@0
|
11 register_for :nitro_xhtml
|
Chris@0
|
12 file_extension :xhtml
|
Chris@0
|
13 title 'Nitro XHTML'
|
Chris@0
|
14
|
Chris@0
|
15 KINDS_NOT_LOC = HTML::KINDS_NOT_LOC
|
Chris@0
|
16
|
Chris@0
|
17 NITRO_RUBY_BLOCK = /
|
Chris@0
|
18 <\?r
|
Chris@0
|
19 (?>
|
Chris@0
|
20 [^\?]*
|
Chris@0
|
21 (?> \?(?!>) [^\?]* )*
|
Chris@0
|
22 )
|
Chris@0
|
23 (?: \?> )?
|
Chris@0
|
24 |
|
Chris@0
|
25 <ruby>
|
Chris@0
|
26 (?>
|
Chris@0
|
27 [^<]*
|
Chris@0
|
28 (?> <(?!\/ruby>) [^<]* )*
|
Chris@0
|
29 )
|
Chris@0
|
30 (?: <\/ruby> )?
|
Chris@0
|
31 |
|
Chris@0
|
32 <%
|
Chris@0
|
33 (?>
|
Chris@0
|
34 [^%]*
|
Chris@0
|
35 (?> %(?!>) [^%]* )*
|
Chris@0
|
36 )
|
Chris@0
|
37 (?: %> )?
|
Chris@0
|
38 /mx
|
Chris@0
|
39
|
Chris@0
|
40 NITRO_VALUE_BLOCK = /
|
Chris@0
|
41 \#
|
Chris@0
|
42 (?:
|
Chris@0
|
43 \{
|
Chris@0
|
44 [^{}]*
|
Chris@0
|
45 (?>
|
Chris@0
|
46 \{ [^}]* \}
|
Chris@0
|
47 (?> [^{}]* )
|
Chris@0
|
48 )*
|
Chris@0
|
49 \}?
|
Chris@0
|
50 | \| [^|]* \|?
|
Chris@0
|
51 | \( [^)]* \)?
|
Chris@0
|
52 | \[ [^\]]* \]?
|
Chris@0
|
53 | \\ [^\\]* \\?
|
Chris@0
|
54 )
|
Chris@0
|
55 /x
|
Chris@0
|
56
|
Chris@0
|
57 NITRO_ENTITY = /
|
Chris@0
|
58 % (?: \#\d+ | \w+ ) ;
|
Chris@0
|
59 /
|
Chris@0
|
60
|
Chris@0
|
61 START_OF_RUBY = /
|
Chris@0
|
62 (?=[<\#%])
|
Chris@0
|
63 < (?: \?r | % | ruby> )
|
Chris@0
|
64 | \# [{(|]
|
Chris@0
|
65 | % (?: \#\d+ | \w+ ) ;
|
Chris@0
|
66 /x
|
Chris@0
|
67
|
Chris@0
|
68 CLOSING_PAREN = Hash.new do |h, p|
|
Chris@0
|
69 h[p] = p
|
Chris@0
|
70 end.update( {
|
Chris@0
|
71 '(' => ')',
|
Chris@0
|
72 '[' => ']',
|
Chris@0
|
73 '{' => '}',
|
Chris@0
|
74 } )
|
Chris@0
|
75
|
Chris@0
|
76 private
|
Chris@0
|
77
|
Chris@0
|
78 def setup
|
Chris@0
|
79 @ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true
|
Chris@0
|
80 @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true
|
Chris@0
|
81 end
|
Chris@0
|
82
|
Chris@0
|
83 def reset_instance
|
Chris@0
|
84 super
|
Chris@0
|
85 @html_scanner.reset
|
Chris@0
|
86 end
|
Chris@0
|
87
|
Chris@0
|
88 def scan_tokens tokens, options
|
Chris@0
|
89
|
Chris@0
|
90 until eos?
|
Chris@0
|
91
|
Chris@0
|
92 if (match = scan_until(/(?=#{START_OF_RUBY})/o) || scan_until(/\z/)) and not match.empty?
|
Chris@0
|
93 @html_scanner.tokenize match
|
Chris@0
|
94
|
Chris@0
|
95 elsif match = scan(/#{NITRO_VALUE_BLOCK}/o)
|
Chris@0
|
96 start_tag = match[0,2]
|
Chris@0
|
97 delimiter = CLOSING_PAREN[start_tag[1,1]]
|
Chris@0
|
98 end_tag = match[-1,1] == delimiter ? delimiter : ''
|
Chris@0
|
99 tokens << [:open, :inline]
|
Chris@0
|
100 tokens << [start_tag, :inline_delimiter]
|
Chris@0
|
101 code = match[start_tag.size .. -1 - end_tag.size]
|
Chris@0
|
102 @ruby_scanner.tokenize code
|
Chris@0
|
103 tokens << [end_tag, :inline_delimiter] unless end_tag.empty?
|
Chris@0
|
104 tokens << [:close, :inline]
|
Chris@0
|
105
|
Chris@0
|
106 elsif match = scan(/#{NITRO_RUBY_BLOCK}/o)
|
Chris@0
|
107 start_tag = '<?r'
|
Chris@0
|
108 end_tag = match[-2,2] == '?>' ? '?>' : ''
|
Chris@0
|
109 tokens << [:open, :inline]
|
Chris@0
|
110 tokens << [start_tag, :inline_delimiter]
|
Chris@0
|
111 code = match[start_tag.size .. -(end_tag.size)-1]
|
Chris@0
|
112 @ruby_scanner.tokenize code
|
Chris@0
|
113 tokens << [end_tag, :inline_delimiter] unless end_tag.empty?
|
Chris@0
|
114 tokens << [:close, :inline]
|
Chris@0
|
115
|
Chris@0
|
116 elsif entity = scan(/#{NITRO_ENTITY}/o)
|
Chris@0
|
117 tokens << [entity, :entity]
|
Chris@0
|
118
|
Chris@0
|
119 elsif scan(/%/)
|
Chris@0
|
120 tokens << [matched, :error]
|
Chris@0
|
121
|
Chris@0
|
122 else
|
Chris@0
|
123 raise_inspect 'else-case reached!', tokens
|
Chris@0
|
124
|
Chris@0
|
125 end
|
Chris@0
|
126
|
Chris@0
|
127 end
|
Chris@0
|
128
|
Chris@0
|
129 tokens
|
Chris@0
|
130
|
Chris@0
|
131 end
|
Chris@0
|
132
|
Chris@0
|
133 end
|
Chris@0
|
134
|
Chris@0
|
135 end
|
Chris@0
|
136 end
|