Chris@909: module CodeRay Chris@909: module Scanners Chris@909: Chris@909: load :html Chris@909: load :ruby Chris@909: Chris@909: # Scanner for HTML ERB templates. Chris@909: class ERB < Scanner Chris@909: Chris@909: register_for :erb Chris@909: title 'HTML ERB Template' Chris@909: Chris@909: KINDS_NOT_LOC = HTML::KINDS_NOT_LOC Chris@909: Chris@909: ERB_RUBY_BLOCK = / Chris@909: (<%(?!%)[-=\#]?) Chris@909: ((?> Chris@909: [^\-%]* # normal* Chris@909: (?> # special Chris@909: (?: %(?!>) | -(?!%>) ) Chris@909: [^\-%]* # normal* Chris@909: )* Chris@909: )) Chris@909: ((?: -?%> )?) Chris@909: /x # :nodoc: Chris@909: Chris@909: START_OF_ERB = / Chris@909: <%(?!%) Chris@909: /x # :nodoc: Chris@909: Chris@909: protected Chris@909: Chris@909: def setup Chris@909: @ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true Chris@909: @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true, :keep_state => true Chris@909: end Chris@909: Chris@909: def reset_instance Chris@909: super Chris@909: @html_scanner.reset Chris@909: end Chris@909: Chris@909: def scan_tokens encoder, options Chris@909: Chris@909: until eos? Chris@909: Chris@909: if (match = scan_until(/(?=#{START_OF_ERB})/o) || scan_rest) and not match.empty? Chris@909: @html_scanner.tokenize match, :tokens => encoder Chris@909: Chris@909: elsif match = scan(/#{ERB_RUBY_BLOCK}/o) Chris@909: start_tag = self[1] Chris@909: code = self[2] Chris@909: end_tag = self[3] Chris@909: Chris@909: encoder.begin_group :inline Chris@909: encoder.text_token start_tag, :inline_delimiter Chris@909: Chris@909: if start_tag == '<%#' Chris@909: encoder.text_token code, :comment Chris@909: else Chris@909: @ruby_scanner.tokenize code, :tokens => encoder Chris@909: end unless code.empty? Chris@909: Chris@909: encoder.text_token end_tag, :inline_delimiter unless end_tag.empty? Chris@909: encoder.end_group :inline Chris@909: Chris@909: else Chris@909: raise_inspect 'else-case reached!', encoder Chris@909: Chris@909: end Chris@909: Chris@909: end Chris@909: Chris@909: encoder Chris@909: Chris@909: end Chris@909: Chris@909: end Chris@909: Chris@909: end Chris@909: end