From 32b4a8b36b04878a761b274293f5708a40a622a5 Mon Sep 17 00:00:00 2001 From: seki Date: Sat, 2 Jan 2016 07:19:58 +0000 Subject: Allow ERB subclass to add token easily. [Feature #11936] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53412 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/erb.rb | 131 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 54 deletions(-) (limited to 'lib') diff --git a/lib/erb.rb b/lib/erb.rb index 73fc574314..5223a280ad 100644 --- a/lib/erb.rb +++ b/lib/erb.rb @@ -371,8 +371,11 @@ class ERB def initialize(src, trim_mode, percent) @src = src @stag = nil + @stags = %w(<%% <%= <%# <%).freeze + @etags = %w(%%> %>).freeze end attr_accessor :stag + attr_reader :stags, :etags def scan; end end @@ -383,12 +386,16 @@ class ERB @trim_mode = trim_mode @percent = percent if @trim_mode == '>' + @scan_reg = /(.*?)(%>\n|#{(stags + etags).join('|')}|\n|\z)/m @scan_line = self.method(:trim_line1) elsif @trim_mode == '<>' + @scan_reg = /(.*?)(%>\n|#{(stags + etags).join('|')}|\n|\z)/m @scan_line = self.method(:trim_line2) elsif @trim_mode == '-' + @scan_reg = /(.*?)(^[ \t]*<%\-|<%\-|-%>\n|-%>|#{(stags + etags).join('|')}|\z)/m @scan_line = self.method(:explicit_trim_line) else + @scan_reg = /(.*?)(#{(stags + etags).join('|')}|\n|\z)/m @scan_line = self.method(:scan_line) end end @@ -420,7 +427,7 @@ class ERB end def scan_line(line) - line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens| + line.scan(@scan_reg) do |tokens| tokens.each do |token| next if token.empty? yield(token) @@ -429,7 +436,7 @@ class ERB end def trim_line1(line) - line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens| + line.scan(@scan_reg) do |tokens| tokens.each do |token| next if token.empty? if token == "%>\n" @@ -444,7 +451,7 @@ class ERB def trim_line2(line) head = nil - line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens| + line.scan(@scan_reg) do |tokens| tokens.each do |token| next if token.empty? head = token unless head @@ -465,7 +472,7 @@ class ERB end def explicit_trim_line(line) - line.scan(/(.*?)(^[ \t]*<%\-|<%\-|<%%|%%>|<%=|<%#|<%|-%>\n|-%>|%>|\z)/m) do |tokens| + line.scan(@scan_reg) do |tokens| tokens.each do |token| next if token.empty? if @stag.nil? && /[ \t]*<%-/ =~ token @@ -492,7 +499,7 @@ class ERB class SimpleScanner < Scanner # :nodoc: def scan - @src.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens| + @src.scan(/(.*?)(#{(stags + etags).join('|')}|\n|\z)/m) do |tokens| tokens.each do |token| next if token.empty? yield(token) @@ -507,8 +514,8 @@ class ERB require 'strscan' class SimpleScanner2 < Scanner # :nodoc: def scan - stag_reg = /(.*?)(<%[%=#]?|\z)/m - etag_reg = /(.*?)(%%?>|\z)/m + stag_reg = /(.*?)(#{stags.join('|')}|\z)/m + etag_reg = /(.*?)(#{etags.join('|')}|\z)/m scanner = StringScanner.new(@src) while ! scanner.eos? scanner.scan(@stag ? etag_reg : stag_reg) @@ -521,8 +528,8 @@ class ERB class ExplicitScanner < Scanner # :nodoc: def scan - stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%=|<%#|<%-|<%|\z)/m - etag_reg = /(.*?)(%%>|-%>|%>|\z)/m + stag_reg = /(.*?)(^[ \t]*<%-|<%-|#{stags.join('|')}|\z)/m + etag_reg = /(.*?)(-%>|#{etags.join('|')}|\z)/m scanner = StringScanner.new(@src) while ! scanner.eos? scanner.scan(@stag ? etag_reg : stag_reg) @@ -602,57 +609,15 @@ class ERB enc = detect_magic_comment(s) || enc out = Buffer.new(self, enc) - content = '' + self.content = '' scanner = make_scanner(s) scanner.scan do |token| next if token.nil? next if token == '' if scanner.stag.nil? - case token - when PercentLine - add_put_cmd(out, content) if content.size > 0 - content = '' - out.push(token.to_s) - out.cr - when :cr - out.cr - when '<%', '<%=', '<%#' - scanner.stag = token - add_put_cmd(out, content) if content.size > 0 - content = '' - when "\n" - content << "\n" - add_put_cmd(out, content) - content = '' - when '<%%' - content << '<%' - else - content << token - end + compile_stag(token, out, scanner) else - case token - when '%>' - case scanner.stag - when '<%' - if content[-1] == ?\n - content.chop! - out.push(content) - out.cr - else - out.push(content) - end - when '<%=' - add_insert_cmd(out, content) - when '<%#' - # out.push("# #{content_dump(content)}") - end - scanner.stag = nil - content = '' - when '%%>' - content << '%>' - else - content << token - end + compile_etag(token, out, scanner) end end add_put_cmd(out, content) if content.size > 0 @@ -660,6 +625,60 @@ class ERB return out.script, enc end + def compile_stag(stag, out, scanner) + case stag + when PercentLine + add_put_cmd(out, content) if content.size > 0 + self.content = '' + out.push(stag.to_s) + out.cr + when :cr + out.cr + when '<%', '<%=', '<%#' + scanner.stag = stag + add_put_cmd(out, content) if content.size > 0 + self.content = '' + when "\n" + content << "\n" + add_put_cmd(out, content) + self.content = '' + when '<%%' + content << '<%' + else + content << stag + end + end + + def compile_etag(etag, out, scanner) + case etag + when '%>' + compile_content(scanner.stag, out) + scanner.stag = nil + self.content = '' + when '%%>' + content << '%>' + else + content << etag + end + end + + def compile_content(stag, out) + case stag + when '<%' + if content[-1] == ?\n + content.chop! + out.push(content) + out.cr + else + out.push(content) + end + when '<%=' + add_insert_cmd(out, content) + when '<%#' + # out.push("# #{content_dump(content)}") + end + end + def prepare_trim_mode(mode) # :nodoc: case mode when 1 @@ -712,6 +731,10 @@ class ERB attr_accessor :post_cmd private + + # A buffered text in #compile + attr_accessor :content + def detect_magic_comment(s) if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s) comment = $1 -- cgit v1.2.3