PageRenderTime 4ms CodeModel.GetById 161ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 2ms

/vendor/bundle/ruby/1.9.1/gems/erubis-2.7.0/contrib/erubis

https://bitbucket.org/sqctest02/sample_app_3_1
Ruby | 3468 lines | 2042 code | 646 blank | 780 comment | 295 complexity | b6ee1e8b2f6e4b4a85b4afb630b90810 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#!/usr/bin/env ruby
   2
   3###
   4### $Release: 2.7.0 $
   5### copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
   6###
   7
   8#--begin of require 'erubis/main'
   9###
  10### $Release: 2.7.0 $
  11### copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
  12###
  13
  14require 'yaml'
  15#--begin of require 'erubis'
  16##
  17## $Release: 2.7.0 $
  18## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
  19##
  20
  21##
  22## an implementation of eRuby
  23##
  24## ex.
  25##   input = <<'END'
  26##    <ul>
  27##     <% for item in @list %>
  28##      <li><%= item %>
  29##          <%== item %></li>
  30##     <% end %>
  31##    </ul>
  32##   END
  33##   list = ['<aaa>', 'b&b', '"ccc"']
  34##   eruby = Erubis::Eruby.new(input)
  35##   puts "--- code ---"
  36##   puts eruby.src
  37##   puts "--- result ---"
  38##   context = Erubis::Context.new()   # or new(:list=>list)
  39##   context[:list] = list
  40##   puts eruby.evaluate(context)
  41##
  42## result:
  43##   --- source ---
  44##   _buf = ''; _buf << '<ul>
  45##   ';  for item in @list 
  46##    _buf << '  <li>'; _buf << ( item ).to_s; _buf << '
  47##   '; _buf << '      '; _buf << Erubis::XmlHelper.escape_xml( item ); _buf << '</li>
  48##   ';  end 
  49##    _buf << '</ul>
  50##   ';
  51##   _buf.to_s
  52##   --- result ---
  53##    <ul>
  54##      <li><aaa>
  55##          &lt;aaa&gt;</li>
  56##      <li>b&b
  57##          b&amp;b</li>
  58##      <li>"ccc"
  59##          &quot;ccc&quot;</li>
  60##    </ul>
  61##
  62
  63
  64module Erubis
  65  VERSION = ('$Release: 2.7.0 $' =~ /([.\d]+)/) && $1
  66end
  67
  68#--begin of require 'erubis/engine'
  69##
  70## $Release: 2.7.0 $
  71## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
  72##
  73
  74
  75#--begin of require 'erubis/generator'
  76##
  77## $Release: 2.7.0 $
  78## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
  79##
  80
  81#--begin of require 'erubis/util'
  82##
  83## $Release: 2.7.0 $
  84## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
  85##
  86
  87module Kernel
  88
  89  ##
  90  ## raise NotImplementedError
  91  ##
  92  def not_implemented     #:doc:
  93    backtrace = caller()
  94    method_name = (backtrace.shift =~ /`(\w+)'$/) && $1
  95    mesg = "class #{self.class.name} must implement abstract method '#{method_name}()'."
  96    #mesg = "#{self.class.name}##{method_name}() is not implemented."
  97    err = NotImplementedError.new mesg
  98    err.set_backtrace backtrace
  99    raise err
 100  end
 101  private :not_implemented
 102
 103end
 104#--end of require 'erubis/util'
 105
 106module Erubis
 107
 108
 109  ##
 110  ## code generator, called by Converter module
 111  ##
 112  module Generator
 113
 114    def self.supported_properties()  # :nodoc:
 115      return [
 116              [:escapefunc,    nil,    "escape function name"],
 117            ]
 118    end
 119
 120    attr_accessor :escapefunc
 121
 122    def init_generator(properties={})
 123      @escapefunc = properties[:escapefunc]
 124    end
 125
 126
 127    ## (abstract) escape text string
 128    ##
 129    ## ex.
 130    ##   def escape_text(text)
 131    ##     return text.dump
 132    ##     # or return "'" + text.gsub(/['\\]/, '\\\\\&') + "'"
 133    ##   end
 134    def escape_text(text)
 135      not_implemented
 136    end
 137
 138    ## return escaped expression code (ex. 'h(...)' or 'htmlspecialchars(...)')
 139    def escaped_expr(code)
 140      code.strip!
 141      return "#{@escapefunc}(#{code})"
 142    end
 143
 144    ## (abstract) add @preamble to src
 145    def add_preamble(src)
 146      not_implemented
 147    end
 148
 149    ## (abstract) add text string to src
 150    def add_text(src, text)
 151      not_implemented
 152    end
 153
 154    ## (abstract) add statement code to src
 155    def add_stmt(src, code)
 156      not_implemented
 157    end
 158
 159    ## (abstract) add expression literal code to src. this is called by add_expr().
 160    def add_expr_literal(src, code)
 161      not_implemented
 162    end
 163
 164    ## (abstract) add escaped expression code to src. this is called by add_expr().
 165    def add_expr_escaped(src, code)
 166      not_implemented
 167    end
 168
 169    ## (abstract) add expression code to src for debug. this is called by add_expr().
 170    def add_expr_debug(src, code)
 171      not_implemented
 172    end
 173
 174    ## (abstract) add @postamble to src
 175    def add_postamble(src)
 176      not_implemented
 177    end
 178
 179
 180  end
 181
 182
 183end
 184#--end of require 'erubis/generator'
 185#--begin of require 'erubis/converter'
 186##
 187## $Release: 2.7.0 $
 188## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
 189##
 190
 191#--already included require 'erubis/util'
 192
 193module Erubis
 194
 195
 196  ##
 197  ## convert
 198  ##
 199  module Converter
 200
 201    attr_accessor :preamble, :postamble, :escape
 202
 203    def self.supported_properties    # :nodoc:
 204      return [
 205              [:preamble,  nil,    "preamble (no preamble when false)"],
 206              [:postamble, nil,    "postamble (no postamble when false)"],
 207              [:escape,    nil,    "escape expression or not in default"],
 208             ]
 209    end
 210
 211    def init_converter(properties={})
 212      @preamble  = properties[:preamble]
 213      @postamble = properties[:postamble]
 214      @escape    = properties[:escape]
 215    end
 216
 217    ## convert input string into target language
 218    def convert(input)
 219      codebuf = ""    # or []
 220      @preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
 221      convert_input(codebuf, input)
 222      @postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
 223      @_proc = nil    # clear cached proc object
 224      return codebuf  # or codebuf.join()
 225    end
 226
 227    protected
 228
 229    ##
 230    ## detect spaces at beginning of line
 231    ##
 232    def detect_spaces_at_bol(text, is_bol)
 233      lspace = nil
 234      if text.empty?
 235        lspace = "" if is_bol
 236      elsif text[-1] == ?\n
 237        lspace = ""
 238      else
 239        rindex = text.rindex(?\n)
 240        if rindex
 241          s = text[rindex+1..-1]
 242          if s =~ /\A[ \t]*\z/
 243            lspace = s
 244            #text = text[0..rindex]
 245            text[rindex+1..-1] = ''
 246          end
 247        else
 248          if is_bol && text =~ /\A[ \t]*\z/
 249            #lspace = text
 250            #text = nil
 251            lspace = text.dup
 252            text[0..-1] = ''
 253          end
 254        end
 255      end
 256      return lspace
 257    end
 258
 259    ##
 260    ## (abstract) convert input to code
 261    ##
 262    def convert_input(codebuf, input)
 263      not_implemented
 264    end
 265
 266  end
 267
 268
 269  module Basic
 270  end
 271
 272
 273  ##
 274  ## basic converter which supports '<% ... %>' notation.
 275  ##
 276  module Basic::Converter
 277    include Erubis::Converter
 278
 279    def self.supported_properties    # :nodoc:
 280      return [
 281              [:pattern,  '<% %>', "embed pattern"],
 282              [:trim,      true,   "trim spaces around <% ... %>"],
 283             ]
 284    end
 285
 286    attr_accessor :pattern, :trim
 287
 288    def init_converter(properties={})
 289      super(properties)
 290      @pattern = properties[:pattern]
 291      @trim    = properties[:trim] != false
 292    end
 293
 294    protected
 295
 296    ## return regexp of pattern to parse eRuby script
 297    def pattern_regexp(pattern)
 298      @prefix, @postfix = pattern.split()   # '<% %>' => '<%', '%>'
 299      #return /(.*?)(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m
 300      #return /(^[ \t]*)?#{@prefix}(=+|\#)?(.*?)-?#{@postfix}([ \t]*\r?\n)?/m
 301      return /#{@prefix}(=+|-|\#|%)?(.*?)([-=])?#{@postfix}([ \t]*\r?\n)?/m
 302    end
 303    module_function :pattern_regexp
 304
 305    #DEFAULT_REGEXP = /(.*?)(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
 306    #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
 307    #DEFAULT_REGEXP = /<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
 308    DEFAULT_REGEXP = pattern_regexp('<% %>')
 309
 310    public
 311
 312    def convert_input(src, input)
 313      pat = @pattern
 314      regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat)
 315      pos = 0
 316      is_bol = true     # is beginning of line
 317      input.scan(regexp) do |indicator, code, tailch, rspace|
 318        match = Regexp.last_match()
 319        len  = match.begin(0) - pos
 320        text = input[pos, len]
 321        pos  = match.end(0)
 322        ch   = indicator ? indicator[0] : nil
 323        lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
 324        is_bol = rspace ? true : false
 325        add_text(src, text) if text && !text.empty?
 326        ## * when '<%= %>', do nothing
 327        ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
 328        if ch == ?=              # <%= %>
 329          rspace = nil if tailch && !tailch.empty?
 330          add_text(src, lspace) if lspace
 331          add_expr(src, code, indicator)
 332          add_text(src, rspace) if rspace
 333        elsif ch == ?\#          # <%# %>
 334          n = code.count("\n") + (rspace ? 1 : 0)
 335          if @trim && lspace && rspace
 336            add_stmt(src, "\n" * n)
 337          else
 338            add_text(src, lspace) if lspace
 339            add_stmt(src, "\n" * n)
 340            add_text(src, rspace) if rspace
 341          end
 342        elsif ch == ?%           # <%% %>
 343          s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}"
 344          add_text(src, s)
 345        else                     # <% %>
 346          if @trim && lspace && rspace
 347            add_stmt(src, "#{lspace}#{code}#{rspace}")
 348          else
 349            add_text(src, lspace) if lspace
 350            add_stmt(src, code)
 351            add_text(src, rspace) if rspace
 352          end
 353        end
 354      end
 355      #rest = $' || input                        # ruby1.8
 356      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
 357      add_text(src, rest)
 358    end
 359
 360    ## add expression code to src
 361    def add_expr(src, code, indicator)
 362      case indicator
 363      when '='
 364        @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
 365      when '=='
 366        @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
 367      when '==='
 368        add_expr_debug(src, code)
 369      end
 370    end
 371
 372  end
 373
 374
 375  module PI
 376  end
 377
 378  ##
 379  ## Processing Instructions (PI) converter for XML.
 380  ## this class converts '<?rb ... ?>' and '${...}' notation.
 381  ##
 382  module PI::Converter
 383    include Erubis::Converter
 384
 385    def self.desc   # :nodoc:
 386      "use processing instructions (PI) instead of '<% %>'"
 387    end
 388
 389    def self.supported_properties    # :nodoc:
 390      return [
 391              [:trim,      true,   "trim spaces around <% ... %>"],
 392              [:pi,        'rb',   "PI (Processing Instrunctions) name"],
 393              [:embchar,   '@',    "char for embedded expression pattern('@{...}@')"],
 394              [:pattern,  '<% %>', "embed pattern"],
 395             ]
 396    end
 397
 398    attr_accessor :pi, :prefix
 399
 400    def init_converter(properties={})
 401      super(properties)
 402      @trim    = properties.fetch(:trim, true)
 403      @pi      = properties[:pi] if properties[:pi]
 404      @embchar = properties[:embchar] || '@'
 405      @pattern = properties[:pattern]
 406      @pattern = '<% %>' if @pattern.nil?  #|| @pattern == true
 407    end
 408
 409    def convert(input)
 410      code = super(input)
 411      return @header || @footer ? "#{@header}#{code}#{@footer}" : code
 412    end
 413
 414    protected
 415
 416    def convert_input(codebuf, input)
 417      unless @regexp
 418        @pi ||= 'e'
 419        ch = Regexp.escape(@embchar)
 420        if @pattern
 421          left, right = @pattern.split(' ')
 422          @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/m
 423        else
 424          @regexp = /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?|#{ch}(!*)?\{(.*?)\}#{ch}/m
 425        end
 426      end
 427      #
 428      is_bol = true
 429      pos = 0
 430      input.scan(@regexp) do |pi_arg, stmt, rspace,
 431                              indicator1, expr1, indicator2, expr2|
 432        match = Regexp.last_match
 433        len = match.begin(0) - pos
 434        text = input[pos, len]
 435        pos = match.end(0)
 436        lspace = stmt ? detect_spaces_at_bol(text, is_bol) : nil
 437        is_bol = stmt && rspace ? true : false
 438        add_text(codebuf, text) # unless text.empty?
 439        #
 440        if stmt
 441          if @trim && lspace && rspace
 442            add_pi_stmt(codebuf, "#{lspace}#{stmt}#{rspace}", pi_arg)
 443          else
 444            add_text(codebuf, lspace) if lspace
 445            add_pi_stmt(codebuf, stmt, pi_arg)
 446            add_text(codebuf, rspace) if rspace
 447          end
 448        else
 449          add_pi_expr(codebuf, expr1 || expr2, indicator1 || indicator2)
 450        end
 451      end
 452      #rest = $' || input                        # ruby1.8
 453      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
 454      add_text(codebuf, rest)
 455    end
 456
 457    #--
 458    #def convert_input(codebuf, input)
 459    #  parse_stmts(codebuf, input)
 460    #  #parse_stmts2(codebuf, input)
 461    #end
 462    #
 463    #def parse_stmts(codebuf, input)
 464    #  #regexp = pattern_regexp(@pattern)
 465    #  @pi ||= 'e'
 466    #  @stmt_pattern ||= /<\?#{@pi}(?:-(\w+))?(\s.*?)\?>([ \t]*\r?\n)?/m
 467    #  is_bol = true
 468    #  pos = 0
 469    #  input.scan(@stmt_pattern) do |pi_arg, code, rspace|
 470    #    match = Regexp.last_match
 471    #    len  = match.begin(0) - pos
 472    #    text = input[pos, len]
 473    #    pos  = match.end(0)
 474    #    lspace = detect_spaces_at_bol(text, is_bol)
 475    #    is_bol = rspace ? true : false
 476    #    parse_exprs(codebuf, text) # unless text.empty?
 477    #    if @trim && lspace && rspace
 478    #      add_pi_stmt(codebuf, "#{lspace}#{code}#{rspace}", pi_arg)
 479    #    else
 480    #      add_text(codebuf, lspace)
 481    #      add_pi_stmt(codebuf, code, pi_arg)
 482    #      add_text(codebuf, rspace)
 483    #    end
 484    #  end
 485    #  rest = $' || input
 486    #  parse_exprs(codebuf, rest)
 487    #end
 488    #
 489    #def parse_exprs(codebuf, input)
 490    #  unless @expr_pattern
 491    #    ch = Regexp.escape(@embchar)
 492    #    if @pattern
 493    #      left, right = @pattern.split(' ')
 494    #      @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}|#{left}(=+)(.*?)#{right}/
 495    #    else
 496    #      @expr_pattern = /#{ch}(!*)?\{(.*?)\}#{ch}/
 497    #    end
 498    #  end
 499    #  pos = 0
 500    #  input.scan(@expr_pattern) do |indicator1, code1, indicator2, code2|
 501    #    indicator = indicator1 || indicator2
 502    #    code = code1 || code2
 503    #    match = Regexp.last_match
 504    #    len  = match.begin(0) - pos
 505    #    text = input[pos, len]
 506    #    pos  = match.end(0)
 507    #    add_text(codebuf, text) # unless text.empty?
 508    #    add_pi_expr(codebuf, code, indicator)
 509    #  end
 510    #  rest = $' || input
 511    #  add_text(codebuf, rest)
 512    #end
 513    #++
 514
 515    def add_pi_stmt(codebuf, code, pi_arg)  # :nodoc:
 516      case pi_arg
 517      when nil      ;  add_stmt(codebuf, code)
 518      when 'header' ;  @header = code
 519      when 'footer' ;  @footer = code
 520      when 'comment';  add_stmt(codebuf, "\n" * code.count("\n"))
 521      when 'value'  ;  add_expr_literal(codebuf, code)
 522      else          ;  add_stmt(codebuf, code)
 523      end
 524    end
 525
 526    def add_pi_expr(codebuf, code, indicator)  # :nodoc:
 527      case indicator
 528      when nil, '', '=='    # @{...}@ or <%== ... %>
 529        @escape == false ? add_expr_literal(codebuf, code) : add_expr_escaped(codebuf, code)
 530      when '!', '='         # @!{...}@ or <%= ... %>
 531        @escape == false ? add_expr_escaped(codebuf, code) : add_expr_literal(codebuf, code)
 532      when '!!', '==='      # @!!{...}@ or <%=== ... %>
 533        add_expr_debug(codebuf, code)
 534      else
 535        # ignore
 536      end
 537    end
 538
 539  end
 540
 541
 542end
 543#--end of require 'erubis/converter'
 544#--begin of require 'erubis/evaluator'
 545##
 546## $Release: 2.7.0 $
 547## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
 548##
 549
 550#--begin of require 'erubis/error'
 551##
 552## $Release: 2.7.0 $
 553## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
 554##
 555
 556module Erubis
 557
 558
 559  ##
 560  ## base error class
 561  ##
 562  class ErubisError < StandardError
 563  end
 564
 565
 566  ##
 567  ## raised when method or function is not supported
 568  ##
 569  class NotSupportedError < ErubisError
 570  end
 571
 572
 573end
 574#--end of require 'erubis/error'
 575#--begin of require 'erubis/context'
 576##
 577## $Release: 2.7.0 $
 578## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
 579##
 580
 581
 582module Erubis
 583
 584
 585  ##
 586  ## context object for Engine#evaluate
 587  ##
 588  ## ex.
 589  ##   template = <<'END'
 590  ##   Hello <%= @user %>!
 591  ##   <% for item in @list %>
 592  ##    - <%= item %>
 593  ##   <% end %>
 594  ##   END
 595  ##
 596  ##   context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
 597  ##   # or
 598  ##   # context = Erubis::Context.new
 599  ##   # context[:user] = 'World'
 600  ##   # context[:list] = ['a', 'b', 'c']
 601  ##
 602  ##   eruby = Erubis::Eruby.new(template)
 603  ##   print eruby.evaluate(context)
 604  ##
 605  class Context
 606    include Enumerable
 607
 608    def initialize(hash=nil)
 609      hash.each do |name, value|
 610        self[name] = value
 611      end if hash
 612    end
 613
 614    def [](key)
 615      return instance_variable_get("@#{key}")
 616    end
 617
 618    def []=(key, value)
 619      return instance_variable_set("@#{key}", value)
 620    end
 621
 622    def keys
 623      return instance_variables.collect { |name| name[1..-1] }
 624    end
 625
 626    def each
 627      instance_variables.each do |name|
 628        key = name[1..-1]
 629        value = instance_variable_get(name)
 630        yield(key, value)
 631      end
 632    end
 633
 634    def to_hash
 635      hash = {}
 636      self.keys.each { |key| hash[key] = self[key] }
 637      return hash
 638    end
 639
 640    def update(context_or_hash)
 641      arg = context_or_hash
 642      if arg.is_a?(Hash)
 643        arg.each do |key, val|
 644          self[key] = val
 645        end
 646      else
 647        arg.instance_variables.each do |varname|
 648          key = varname[1..-1]
 649          val = arg.instance_variable_get(varname)
 650          self[key] = val
 651        end
 652      end
 653    end
 654
 655  end
 656
 657
 658end
 659#--end of require 'erubis/context'
 660
 661
 662module Erubis
 663
 664  EMPTY_BINDING = binding()
 665
 666
 667  ##
 668  ## evaluate code
 669  ##
 670  module Evaluator
 671
 672    def self.supported_properties    # :nodoc:
 673      return []
 674    end
 675
 676    attr_accessor :src, :filename
 677
 678    def init_evaluator(properties)
 679      @filename = properties[:filename]
 680    end
 681
 682    def result(*args)
 683      raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
 684    end
 685
 686    def evaluate(*args)
 687      raise NotSupportedError.new("evaluation of code except Ruby is not supported.")
 688    end
 689
 690  end
 691
 692
 693  ##
 694  ## evaluator for Ruby
 695  ##
 696  module RubyEvaluator
 697    include Evaluator
 698
 699    def self.supported_properties    # :nodoc:
 700      list = Evaluator.supported_properties
 701      return list
 702    end
 703
 704    ## eval(@src) with binding object
 705    def result(_binding_or_hash=TOPLEVEL_BINDING)
 706      _arg = _binding_or_hash
 707      if _arg.is_a?(Hash)
 708        _b = binding()
 709        eval _arg.collect{|k,v| "#{k} = _arg[#{k.inspect}]; "}.join, _b
 710      elsif _arg.is_a?(Binding)
 711        _b = _arg
 712      elsif _arg.nil?
 713        _b = binding()
 714      else
 715        raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.")
 716      end
 717      return eval(@src, _b, (@filename || '(erubis'))
 718    end
 719
 720    ## invoke context.instance_eval(@src)
 721    def evaluate(_context=Context.new)
 722      _context = Context.new(_context) if _context.is_a?(Hash)
 723      #return _context.instance_eval(@src, @filename || '(erubis)')
 724      #@_proc ||= eval("proc { #{@src} }", Erubis::EMPTY_BINDING, @filename || '(erubis)')
 725      @_proc ||= eval("proc { #{@src} }", binding(), @filename || '(erubis)')
 726      return _context.instance_eval(&@_proc)
 727    end
 728
 729    ## if object is an Class or Module then define instance method to it,
 730    ## else define singleton method to it.
 731    def def_method(object, method_name, filename=nil)
 732      m = object.is_a?(Module) ? :module_eval : :instance_eval
 733      object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(erubis)')
 734    end
 735
 736
 737  end
 738
 739
 740end
 741#--end of require 'erubis/evaluator'
 742#--already included require 'erubis/context'
 743
 744
 745module Erubis
 746
 747
 748  ##
 749  ## (abstract) abstract engine class.
 750  ## subclass must include evaluator and converter module.
 751  ##
 752  class Engine
 753    #include Evaluator
 754    #include Converter
 755    #include Generator
 756
 757    def initialize(input=nil, properties={})
 758      #@input = input
 759      init_generator(properties)
 760      init_converter(properties)
 761      init_evaluator(properties)
 762      @src    = convert(input) if input
 763    end
 764
 765
 766    ##
 767    ## convert input string and set it to @src
 768    ##
 769    def convert!(input)
 770      @src = convert(input)
 771    end
 772
 773
 774    ##
 775    ## load file, write cache file, and return engine object.
 776    ## this method create code cache file automatically.
 777    ## cachefile name can be specified with properties[:cachename],
 778    ## or filname + 'cache' is used as default.
 779    ##
 780    def self.load_file(filename, properties={})
 781      cachename = properties[:cachename] || (filename + '.cache')
 782      properties[:filename] = filename
 783      timestamp = File.mtime(filename)
 784      if test(?f, cachename) && timestamp == File.mtime(cachename)
 785        engine = self.new(nil, properties)
 786        engine.src = File.read(cachename)
 787      else
 788        input = File.open(filename, 'rb') {|f| f.read }
 789        engine = self.new(input, properties)
 790        tmpname = cachename + rand().to_s[1,8]
 791        File.open(tmpname, 'wb') {|f| f.write(engine.src) }
 792        File.rename(tmpname, cachename)
 793        File.utime(timestamp, timestamp, cachename)
 794      end
 795      engine.src.untaint   # ok?
 796      return engine
 797    end
 798
 799
 800    ##
 801    ## helper method to convert and evaluate input text with context object.
 802    ## context may be Binding, Hash, or Object.
 803    ##
 804    def process(input, context=nil, filename=nil)
 805      code = convert(input)
 806      filename ||= '(erubis)'
 807      if context.is_a?(Binding)
 808        return eval(code, context, filename)
 809      else
 810        context = Context.new(context) if context.is_a?(Hash)
 811        return context.instance_eval(code, filename)
 812      end
 813    end
 814
 815
 816    ##
 817    ## helper method evaluate Proc object with contect object.
 818    ## context may be Binding, Hash, or Object.
 819    ##
 820    def process_proc(proc_obj, context=nil, filename=nil)
 821      if context.is_a?(Binding)
 822        filename ||= '(erubis)'
 823        return eval(proc_obj, context, filename)
 824      else
 825        context = Context.new(context) if context.is_a?(Hash)
 826        return context.instance_eval(&proc_obj)
 827      end
 828    end
 829
 830
 831  end  # end of class Engine
 832
 833
 834  ##
 835  ## (abstract) base engine class for Eruby, Eperl, Ejava, and so on.
 836  ## subclass must include generator.
 837  ##
 838  class Basic::Engine < Engine
 839    include Evaluator
 840    include Basic::Converter
 841    include Generator
 842  end
 843
 844
 845  class PI::Engine < Engine
 846    include Evaluator
 847    include PI::Converter
 848    include Generator
 849  end
 850
 851
 852end
 853#--end of require 'erubis/engine'
 854#require 'erubis/generator'
 855#require 'erubis/converter'
 856#require 'erubis/evaluator'
 857#require 'erubis/error'
 858#require 'erubis/context'
 859#requier 'erubis/util'
 860#--begin of require 'erubis/helper'
 861##
 862## $Release: 2.7.0 $
 863## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
 864##
 865
 866
 867module Erubis
 868
 869  ##
 870  ## helper for xml
 871  ##
 872  module XmlHelper
 873
 874    module_function
 875
 876    ESCAPE_TABLE = {
 877      '&' => '&amp;',
 878      '<' => '&lt;',
 879      '>' => '&gt;',
 880      '"' => '&quot;',
 881      "'" => '&#039;',
 882    }
 883
 884    def escape_xml(value)
 885      value.to_s.gsub(/[&<>"]/) { |s| ESCAPE_TABLE[s] }   # or /[&<>"']/
 886      #value.to_s.gsub(/[&<>"]/) { ESCAPE_TABLE[$&] }
 887    end
 888
 889    def escape_xml2(value)
 890      return value.to_s.gsub(/\&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;').gsub(/"/,'&quot;')
 891    end
 892
 893    alias h escape_xml
 894    alias html_escape escape_xml
 895
 896    def url_encode(str)
 897      return str.gsub(/[^-_.a-zA-Z0-9]+/) { |s|
 898        s.unpack('C*').collect { |i| "%%%02X" % i }.join
 899      }
 900    end
 901
 902    alias u url_encode
 903
 904  end
 905
 906
 907end
 908#--end of require 'erubis/helper'
 909#--begin of require 'erubis/enhancer'
 910##
 911## $Release: 2.7.0 $
 912## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
 913##
 914
 915
 916module Erubis
 917
 918
 919  ##
 920  ## switch '<%= ... %>' to escaped and '<%== ... %>' to unescaped
 921  ##
 922  ## ex.
 923  ##   class XmlEruby < Eruby
 924  ##     include EscapeEnhancer
 925  ##   end
 926  ##
 927  ## this is language-indenedent.
 928  ##
 929  module EscapeEnhancer
 930
 931    def self.desc   # :nodoc:
 932      "switch '<%= %>' to escaped and '<%== %>' to unescaped"
 933    end
 934
 935    #--
 936    #def self.included(klass)
 937    #  klass.class_eval <<-END
 938    #    alias _add_expr_literal add_expr_literal
 939    #    alias _add_expr_escaped add_expr_escaped
 940    #    alias add_expr_literal _add_expr_escaped
 941    #    alias add_expr_escaped _add_expr_literal
 942    #  END
 943    #end
 944    #++
 945
 946    def add_expr(src, code, indicator)
 947      case indicator
 948      when '='
 949        @escape ? add_expr_literal(src, code) : add_expr_escaped(src, code)
 950      when '=='
 951        @escape ? add_expr_escaped(src, code) : add_expr_literal(src, code)
 952      when '==='
 953        add_expr_debug(src, code)
 954      end
 955    end
 956
 957  end
 958
 959
 960  #--
 961  ## (obsolete)
 962  #module FastEnhancer
 963  #end
 964  #++
 965
 966
 967  ##
 968  ## use $stdout instead of string
 969  ##
 970  ## this is only for Eruby.
 971  ##
 972  module StdoutEnhancer
 973
 974    def self.desc   # :nodoc:
 975      "use $stdout instead of array buffer or string buffer"
 976    end
 977
 978    def add_preamble(src)
 979      src << "#{@bufvar} = $stdout;"
 980    end
 981
 982    def add_postamble(src)
 983      src << "\n''\n"
 984    end
 985
 986  end
 987
 988
 989  ##
 990  ## use print statement instead of '_buf << ...'
 991  ##
 992  ## this is only for Eruby.
 993  ##
 994  module PrintOutEnhancer
 995
 996    def self.desc   # :nodoc:
 997      "use print statement instead of '_buf << ...'"
 998    end
 999
1000    def add_preamble(src)
1001    end
1002
1003    def add_text(src, text)
1004      src << " print '#{escape_text(text)}';" unless text.empty?
1005    end
1006
1007    def add_expr_literal(src, code)
1008      src << " print((#{code}).to_s);"
1009    end
1010
1011    def add_expr_escaped(src, code)
1012      src << " print #{escaped_expr(code)};"
1013    end
1014
1015    def add_postamble(src)
1016      src << "\n" unless src[-1] == ?\n
1017    end
1018
1019  end
1020
1021
1022  ##
1023  ## enable print function
1024  ##
1025  ## Notice: use Eruby#evaluate() and don't use Eruby#result()
1026  ## to be enable print function.
1027  ##
1028  ## this is only for Eruby.
1029  ##
1030  module PrintEnabledEnhancer
1031
1032    def self.desc   # :nodoc:
1033      "enable to use print function in '<% %>'"
1034    end
1035
1036    def add_preamble(src)
1037      src << "@_buf = "
1038      super
1039    end
1040
1041    def print(*args)
1042      args.each do |arg|
1043        @_buf << arg.to_s
1044      end
1045    end
1046
1047    def evaluate(context=nil)
1048      _src = @src
1049      if context.is_a?(Hash)
1050        context.each do |key, val| instance_variable_set("@#{key}", val) end
1051      elsif context
1052        context.instance_variables.each do |name|
1053          instance_variable_set(name, context.instance_variable_get(name))
1054        end
1055      end
1056      return instance_eval(_src, (@filename || '(erubis)'))
1057    end
1058
1059  end
1060
1061
1062  ##
1063  ## return array instead of string
1064  ##
1065  ## this is only for Eruby.
1066  ##
1067  module ArrayEnhancer
1068
1069    def self.desc   # :nodoc:
1070      "return array instead of string"
1071    end
1072
1073    def add_preamble(src)
1074      src << "#{@bufvar} = [];"
1075    end
1076
1077    def add_postamble(src)
1078      src << "\n" unless src[-1] == ?\n
1079      src << "#{@bufvar}\n"
1080    end
1081
1082  end
1083
1084
1085  ##
1086  ## use an Array object as buffer (included in Eruby by default)
1087  ##
1088  ## this is only for Eruby.
1089  ##
1090  module ArrayBufferEnhancer
1091
1092    def self.desc   # :nodoc:
1093      "use an Array object for buffering (included in Eruby class)"
1094    end
1095
1096    def add_preamble(src)
1097      src << "_buf = [];"
1098    end
1099
1100    def add_postamble(src)
1101      src << "\n" unless src[-1] == ?\n
1102      src << "_buf.join\n"
1103    end
1104
1105  end
1106
1107
1108  ##
1109  ## use String class for buffering
1110  ##
1111  ## this is only for Eruby.
1112  ##
1113  module StringBufferEnhancer
1114
1115    def self.desc   # :nodoc:
1116      "use a String object for buffering"
1117    end
1118
1119    def add_preamble(src)
1120      src << "#{@bufvar} = '';"
1121    end
1122
1123    def add_postamble(src)
1124      src << "\n" unless src[-1] == ?\n
1125      src << "#{@bufvar}.to_s\n"
1126    end
1127
1128  end
1129
1130
1131  ##
1132  ## use StringIO class for buffering
1133  ##
1134  ## this is only for Eruby.
1135  ##
1136  module StringIOEnhancer  # :nodoc:
1137
1138    def self.desc   # :nodoc:
1139      "use a StringIO object for buffering"
1140    end
1141
1142    def add_preamble(src)
1143      src << "#{@bufvar} = StringIO.new;"
1144    end
1145
1146    def add_postamble(src)
1147      src << "\n" unless src[-1] == ?\n
1148      src << "#{@bufvar}.string\n"
1149    end
1150
1151  end
1152
1153
1154  ##
1155  ## set buffer variable name to '_erbout' as well as '_buf'
1156  ##
1157  ## this is only for Eruby.
1158  ##
1159  module ErboutEnhancer
1160
1161    def self.desc   # :nodoc:
1162      "set '_erbout = _buf = \"\";' to be compatible with ERB."
1163    end
1164
1165    def add_preamble(src)
1166      src << "_erbout = #{@bufvar} = '';"
1167    end
1168
1169    def add_postamble(src)
1170      src << "\n" unless src[-1] == ?\n
1171      src << "#{@bufvar}.to_s\n"
1172    end
1173
1174  end
1175
1176
1177  ##
1178  ## remove text and leave code, especially useful when debugging.
1179  ##
1180  ## ex.
1181  ##   $ erubis -s -E NoText file.eruby | more
1182  ##
1183  ## this is language independent.
1184  ##
1185  module NoTextEnhancer
1186
1187    def self.desc   # :nodoc:
1188      "remove text and leave code (useful when debugging)"
1189    end
1190
1191    def add_text(src, text)
1192      src << ("\n" * text.count("\n"))
1193      if text[-1] != ?\n
1194        text =~ /^(.*?)\z/
1195        src << (' ' * $1.length)
1196      end
1197    end
1198
1199  end
1200
1201
1202  ##
1203  ## remove code and leave text, especially useful when validating HTML tags.
1204  ##
1205  ## ex.
1206  ##   $ erubis -s -E NoCode file.eruby | tidy -errors
1207  ##
1208  ## this is language independent.
1209  ##
1210  module NoCodeEnhancer
1211
1212    def self.desc   # :nodoc:
1213      "remove code and leave text (useful when validating HTML)"
1214    end
1215
1216    def add_preamble(src)
1217    end
1218
1219    def add_postamble(src)
1220    end
1221
1222    def add_text(src, text)
1223      src << text
1224    end
1225
1226    def add_expr(src, code, indicator)
1227      src << "\n" * code.count("\n")
1228    end
1229
1230    def add_stmt(src, code)
1231      src << "\n" * code.count("\n")
1232    end
1233
1234  end
1235
1236
1237  ##
1238  ## get convert faster, but spaces around '<%...%>' are not trimmed.
1239  ##
1240  ## this is language-independent.
1241  ##
1242  module SimplifyEnhancer
1243
1244    def self.desc   # :nodoc:
1245      "get convert faster but leave spaces around '<% %>'"
1246    end
1247
1248    #DEFAULT_REGEXP = /(^[ \t]*)?<%(=+|\#)?(.*?)-?%>([ \t]*\r?\n)?/m
1249    SIMPLE_REGEXP = /<%(=+|\#)?(.*?)-?%>/m
1250
1251    def convert(input)
1252      src = ""
1253      add_preamble(src)
1254      #regexp = pattern_regexp(@pattern)
1255      pos = 0
1256      input.scan(SIMPLE_REGEXP) do |indicator, code|
1257        match = Regexp.last_match
1258        index = match.begin(0)
1259        text  = input[pos, index - pos]
1260        pos   = match.end(0)
1261        add_text(src, text)
1262        if !indicator              # <% %>
1263          add_stmt(src, code)
1264        elsif indicator[0] == ?\#  # <%# %>
1265          n = code.count("\n")
1266          add_stmt(src, "\n" * n)
1267        else                       # <%= %>
1268          add_expr(src, code, indicator)
1269        end
1270      end
1271      #rest = $' || input                      # ruby1.8
1272      rest = pos == 0 ? input : input[pos..-1]  # ruby1.9
1273      add_text(src, rest)
1274      add_postamble(src)
1275      return src
1276    end
1277
1278  end
1279
1280
1281  ##
1282  ## enable to use other embedded expression pattern (default is '\[= =\]').
1283  ##
1284  ## notice! this is an experimental. spec may change in the future.
1285  ##
1286  ## ex.
1287  ##   input = <<END
1288  ##   <% for item in list %>
1289  ##     <%= item %> : <%== item %>
1290  ##     [= item =] : [== item =]
1291  ##   <% end %>
1292  ##   END
1293  ##
1294  ##   class BiPatternEruby
1295  ##     include BiPatternEnhancer
1296  ##   end
1297  ##   eruby = BiPatternEruby.new(input, :bipattern=>'\[= =\]')
1298  ##   list = ['<a>', 'b&b', '"c"']
1299  ##   print eruby.result(binding())
1300  ##
1301  ##   ## output
1302  ##     <a> : &lt;a&gt;
1303  ##     <a> : &lt;a&gt;
1304  ##     b&b : b&amp;b
1305  ##     b&b : b&amp;b
1306  ##     "c" : &quot;c&quot;
1307  ##     "c" : &quot;c&quot;
1308  ##
1309  ## this is language independent.
1310  ##
1311  module BiPatternEnhancer
1312
1313    def self.desc   # :nodoc:
1314      "another embedded expression pattern (default '\[= =\]')."
1315    end
1316
1317    def initialize(input, properties={})
1318      self.bipattern = properties[:bipattern]    # or '\$\{ \}'
1319      super
1320    end
1321
1322    ## when pat is nil then '\[= =\]' is used
1323    def bipattern=(pat)   # :nodoc:
1324      @bipattern = pat || '\[= =\]'
1325      pre, post = @bipattern.split()
1326      @bipattern_regexp = /(.*?)#{pre}(=*)(.*?)#{post}/m
1327    end
1328
1329    def add_text(src, text)
1330      return unless text
1331      m = nil
1332      text.scan(@bipattern_regexp) do |txt, indicator, code|
1333        m = Regexp.last_match
1334        super(src, txt)
1335        add_expr(src, code, '=' + indicator)
1336      end
1337      #rest = $' || text                    # ruby1.8
1338      rest = m ? text[m.end(0)..-1] : text  # ruby1.9
1339      super(src, rest)
1340    end
1341
1342  end
1343
1344
1345  ##
1346  ## regards lines starting with '^[ \t]*%' as program code
1347  ##
1348  ## in addition you can specify prefix character (default '%')
1349  ##
1350  ## this is language-independent.
1351  ##
1352  module PrefixedLineEnhancer
1353
1354    def self.desc   # :nodoc:
1355      "regard lines matched to '^[ \t]*%' as program code"
1356    end
1357
1358    def init_generator(properties={})
1359      super
1360      @prefixchar = properties[:prefixchar]
1361    end
1362
1363    def add_text(src, text)
1364      unless @prefixrexp
1365        @prefixchar ||= '%'
1366        @prefixrexp = Regexp.compile("^([ \\t]*)\\#{@prefixchar}(.*?\\r?\\n)")
1367      end
1368      pos = 0
1369      text2 = ''
1370      text.scan(@prefixrexp) do
1371        space = $1
1372        line  = $2
1373        space, line = '', $1 unless $2
1374        match = Regexp.last_match
1375        len   = match.begin(0) - pos
1376        str   = text[pos, len]
1377        pos   = match.end(0)
1378        if text2.empty?
1379          text2 = str
1380        else
1381          text2 << str
1382        end
1383        if line[0, 1] == @prefixchar
1384          text2 << space << line
1385        else
1386          super(src, text2)
1387          text2 = ''
1388          add_stmt(src, space + line)
1389        end
1390      end
1391      #rest = pos == 0 ? text : $'             # ruby1.8
1392      rest = pos == 0 ? text : text[pos..-1]   # ruby1.9
1393      unless text2.empty?
1394        text2 << rest if rest
1395        rest = text2
1396      end
1397      super(src, rest)
1398    end
1399
1400  end
1401
1402
1403  ##
1404  ## regards lines starting with '%' as program code
1405  ##
1406  ## this is for compatibility to eruby and ERB.
1407  ##
1408  ## this is language-independent.
1409  ##
1410  module PercentLineEnhancer
1411    include PrefixedLineEnhancer
1412
1413    def self.desc   # :nodoc:
1414      "regard lines starting with '%' as program code"
1415    end
1416
1417    #--
1418    #def init_generator(properties={})
1419    #  super
1420    #  @prefixchar = '%'
1421    #  @prefixrexp = /^\%(.*?\r?\n)/
1422    #end
1423    #++
1424
1425    def add_text(src, text)
1426      unless @prefixrexp
1427        @prefixchar = '%'
1428        @prefixrexp = /^\%(.*?\r?\n)/
1429      end
1430      super(src, text)
1431    end
1432
1433  end
1434
1435
1436  ##
1437  ## [experimental] allow header and footer in eRuby script
1438  ##
1439  ## ex.
1440  ##   ====================
1441  ##   ## without header and footer
1442  ##   $ cat ex1.eruby
1443  ##   <% def list_items(list) %>
1444  ##   <%   for item in list %>
1445  ##   <li><%= item %></li>
1446  ##   <%   end %>
1447  ##   <% end %>
1448  ##
1449  ##   $ erubis -s ex1.eruby
1450  ##   _buf = []; def list_items(list)
1451  ##   ;   for item in list
1452  ##   ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
1453  ##   ';   end
1454  ##   ; end
1455  ##   ;
1456  ##   _buf.join
1457  ##
1458  ##   ## with header and footer
1459  ##   $ cat ex2.eruby
1460  ##   <!--#header:
1461  ##   def list_items(list)
1462  ##    #-->
1463  ##   <%  for item in list %>
1464  ##   <li><%= item %></li>
1465  ##   <%  end %>
1466  ##   <!--#footer:
1467  ##   end
1468  ##    #-->
1469  ##
1470  ##   $ erubis -s -c HeaderFooterEruby ex4.eruby
1471  ##
1472  ##   def list_items(list)
1473  ##    _buf = []; _buf << '
1474  ##   ';  for item in list
1475  ##   ; _buf << '<li>'; _buf << ( item ).to_s; _buf << '</li>
1476  ##   ';  end
1477  ##   ; _buf << '
1478  ##   ';
1479  ##   _buf.join
1480  ##   end
1481  ##
1482  ##   ====================
1483  ##
1484  ## this is language-independent.
1485  ##
1486  module HeaderFooterEnhancer
1487
1488    def self.desc   # :nodoc:
1489      "allow header/footer in document (ex. '<!--#header: #-->')"
1490    end
1491
1492    HEADER_FOOTER_PATTERN = /(.*?)(^[ \t]*)?<!--\#(\w+):(.*?)\#-->([ \t]*\r?\n)?/m
1493
1494    def add_text(src, text)
1495      m = nil
1496      text.scan(HEADER_FOOTER_PATTERN) do |txt, lspace, word, content, rspace|
1497        m = Regexp.last_match
1498        flag_trim = @trim && lspace && rspace
1499        super(src, txt)
1500        content = "#{lspace}#{content}#{rspace}" if flag_trim
1501        super(src, lspace) if !flag_trim && lspace
1502        instance_variable_set("@#{word}", content)
1503        super(src, rspace) if !flag_trim && rspace
1504      end
1505      #rest = $' || text                    # ruby1.8
1506      rest = m ? text[m.end(0)..-1] : text  # ruby1.9
1507      super(src, rest)
1508    end
1509
1510    attr_accessor :header, :footer
1511
1512    def convert(input)
1513      source = super
1514      return @src = "#{@header}#{source}#{@footer}"
1515    end
1516
1517  end
1518
1519
1520  ##
1521  ## delete indentation of HTML.
1522  ##
1523  ## this is language-independent.
1524  ##
1525  module DeleteIndentEnhancer
1526
1527    def self.desc   # :nodoc:
1528      "delete indentation of HTML."
1529    end
1530
1531    def convert_input(src, input)
1532      input = input.gsub(/^[ \t]+</, '<')
1533      super(src, input)
1534    end
1535
1536  end
1537
1538
1539  ##
1540  ## convert "<h1><%=title%></h1>" into "_buf << %Q`<h1>#{title}</h1>`"
1541  ##
1542  ## this is only for Eruby.
1543  ##
1544  module InterpolationEnhancer
1545
1546    def self.desc   # :nodoc:
1547      "convert '<p><%=text%></p>' into '_buf << %Q`<p>\#{text}</p>`'"
1548    end
1549
1550    def convert_input(src, input)
1551      pat = @pattern
1552      regexp = pat.nil? || pat == '<% %>' ? Basic::Converter::DEFAULT_REGEXP : pattern_regexp(pat)
1553      pos = 0
1554      is_bol = true     # is beginning of line
1555      str = ''
1556      input.scan(regexp) do |indicator, code, tailch, rspace|
1557        match = Regexp.last_match()
1558        len  = match.begin(0) - pos
1559        text = input[pos, len]
1560        pos  = match.end(0)
1561        ch   = indicator ? indicator[0] : nil
1562        lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol)
1563        is_bol = rspace ? true : false
1564        _add_text_to_str(str, text)
1565        ## * when '<%= %>', do nothing
1566        ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>'
1567        if ch == ?=              # <%= %>
1568          rspace = nil if tailch && !tailch.empty?
1569          str << lspace if lspace
1570          add_expr(str, code, indicator)
1571          str << rspace if rspace
1572        elsif ch == ?\#          # <%# %>
1573          n = code.count("\n") + (rspace ? 1 : 0)
1574          if @trim && lspace && rspace
1575            add_text(src, str)
1576            str = ''
1577            add_stmt(src, "\n" * n)
1578          else
1579            str << lspace if lspace
1580            add_text(src, str)
1581            str = ''
1582            add_stmt(src, "\n" * n)
1583            str << rspace if rspace
1584          end
1585        else                     # <% %>
1586          if @trim && lspace && rspace
1587            add_text(src, str)
1588            str = ''
1589            add_stmt(src, "#{lspace}#{code}#{rspace}")
1590          else
1591            str << lspace if lspace
1592            add_text(src, str)
1593            str = ''
1594            add_stmt(src, code)
1595            str << rspace if rspace
1596          end
1597        end
1598      end
1599      #rest = $' || input                       # ruby1.8
1600      rest = pos == 0 ? input : input[pos..-1]  # ruby1.9
1601      _add_text_to_str(str, rest)
1602      add_text(src, str)
1603    end
1604
1605    def add_text(src, text)
1606      return if !text || text.empty?
1607      #src << " _buf << %Q`" << text << "`;"
1608      if text[-1] == ?\n
1609        text[-1] = "\\n"
1610        src << " #{@bufvar} << %Q`#{text}`\n"
1611      else
1612        src << " #{@bufvar} << %Q`#{text}`;"
1613      end
1614    end
1615
1616    def _add_text_to_str(str, text)
1617      return if !text || text.empty?
1618      str << text.gsub(/[`\#\\]/, '\\\\\&')
1619    end
1620
1621    def add_expr_escaped(str, code)
1622      str << "\#{#{escaped_expr(code)}}"
1623    end
1624
1625    def add_expr_literal(str, code)
1626      str << "\#{#{code}}"
1627    end
1628
1629  end
1630
1631
1632end
1633#--end of require 'erubis/enhancer'
1634#require 'erubis/tiny'
1635#--begin of require 'erubis/engine/eruby'
1636##
1637## $Release: 2.7.0 $
1638## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
1639##
1640
1641#--already included require 'erubis/engine'
1642#--already included require 'erubis/enhancer'
1643
1644
1645module Erubis
1646
1647
1648  ##
1649  ## code generator for Ruby
1650  ##
1651  module RubyGenerator
1652    include Generator
1653    #include ArrayBufferEnhancer
1654    include StringBufferEnhancer
1655
1656    def init_generator(properties={})
1657      super
1658      @escapefunc ||= "Erubis::XmlHelper.escape_xml"
1659      @bufvar     = properties[:bufvar] || "_buf"
1660    end
1661
1662    def self.supported_properties()  # :nodoc:
1663      return []
1664    end
1665
1666    def escape_text(text)
1667      text.gsub(/['\\]/, '\\\\\&')   # "'" => "\\'",  '\\' => '\\\\'
1668    end
1669
1670    def escaped_expr(code)
1671      return "#{@escapefunc}(#{code})"
1672    end
1673
1674    #--
1675    #def add_preamble(src)
1676    #  src << "#{@bufvar} = [];"
1677    #end
1678    #++
1679
1680    def add_text(src, text)
1681      src << " #{@bufvar} << '" << escape_text(text) << "';" unless text.empty?
1682    end
1683
1684    def add_stmt(src, code)
1685      #src << code << ';'
1686      src << code
1687      src << ';' unless code[-1] == ?\n
1688    end
1689
1690    def add_expr_literal(src, code)
1691      src << " #{@bufvar} << (" << code << ').to_s;'
1692    end
1693
1694    def add_expr_escaped(src, code)
1695      src << " #{@bufvar} << " << escaped_expr(code) << ';'
1696    end
1697
1698    def add_expr_debug(src, code)
1699      code.strip!
1700      s = (code.dump =~ /\A"(.*)"\z/) && $1
1701      src << ' $stderr.puts("*** debug: ' << s << '=#{(' << code << ').inspect}");'
1702    end
1703
1704    #--
1705    #def add_postamble(src)
1706    #  src << "\n#{@bufvar}.join\n"
1707    #end
1708    #++
1709
1710  end
1711
1712
1713  ##
1714  ## engine for Ruby
1715  ##
1716  class Eruby < Basic::Engine
1717    include RubyEvaluator
1718    include RubyGenerator
1719  end
1720
1721
1722  ##
1723  ## fast engine for Ruby
1724  ##
1725  class FastEruby < Eruby
1726    include InterpolationEnhancer
1727  end
1728
1729
1730  ##
1731  ## swtich '<%= %>' to escaped and '<%== %>' to not escaped
1732  ##
1733  class EscapedEruby < Eruby
1734    include EscapeEnhancer
1735  end
1736
1737
1738  ##
1739  ## sanitize expression (<%= ... %>) by default
1740  ##
1741  ## this is equivalent to EscapedEruby and is prepared only for compatibility.
1742  ##
1743  class XmlEruby < Eruby
1744    include EscapeEnhancer
1745  end
1746
1747
1748  class PI::Eruby < PI::Engine
1749    include RubyEvaluator
1750    include RubyGenerator
1751
1752    def init_converter(properties={})
1753      @pi = 'rb'
1754      super(properties)
1755    end
1756
1757  end
1758
1759
1760end
1761#--end of require 'erubis/engine/eruby'
1762#require 'erubis/engine/enhanced'    # enhanced eruby engines
1763#require 'erubis/engine/optimized'   # generates optimized ruby code
1764#require 'erubis/engine/ephp'
1765#require 'erubis/engine/ec'
1766#require 'erubis/engine/ejava'
1767#require 'erubis/engine/escheme'
1768#require 'erubis/engine/eperl'
1769#require 'erubis/engine/ejavascript'
1770
1771#--begin of require 'erubis/local-setting'
1772##
1773## $Release: 2.7.0 $
1774## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
1775##
1776
1777##
1778## you can add site-local settings here.
1779## this files is required by erubis.rb
1780##
1781#--end of require 'erubis/local-setting'
1782#--end of require 'erubis'
1783#--begin of require 'erubis/tiny'
1784##
1785## $Release: 2.7.0 $
1786## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
1787##
1788
1789module Erubis
1790
1791  ##
1792  ## tiny and the simplest implementation of eRuby
1793  ##
1794  ## ex.
1795  ##   eruby = TinyEruby.new(File.read('example.rhtml'))
1796  ##   print eruby.src                 # print ruby code
1797  ##   print eruby.result(binding())   # eval ruby code with Binding object
1798  ##   print eruby.evalute(context)    # eval ruby code with context object
1799  ##
1800  class TinyEruby
1801
1802    def initialize(input=nil)
1803      @src = convert(input) if input
1804    end
1805    attr_reader :src
1806
1807    EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m
1808
1809    def convert(input)
1810      src = "_buf = '';"           # preamble
1811      pos = 0
1812      input.scan(EMBEDDED_PATTERN) do |indicator, code|
1813        m = Regexp.last_match
1814        text = input[pos...m.begin(0)]
1815        pos  = m.end(0)
1816        #src << " _buf << '" << escape_text(text) << "';"
1817        text.gsub!(/['\\]/, '\\\\\&')
1818        src << " _buf << '" << text << "';" unless text.empty?
1819        if !indicator              # <% %>
1820          src << code << ";"
1821        elsif indicator == '#'     # <%# %>
1822          src << ("\n" * code.count("\n"))
1823        else                       # <%= %>
1824          src << " _buf << (" << code << ").to_s;"
1825        end
1826      end
1827      #rest = $' || input                        # ruby1.8
1828      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
1829      #src << " _buf << '" << escape_text(rest) << "';"
1830      rest.gsub!(/['\\]/, '\\\\\&')
1831      src << " _buf << '" << rest << "';" unless rest.empty?
1832      src << "\n_buf.to_s\n"       # postamble
1833      return src
1834    end
1835
1836    #def escape_text(text)
1837    #  return text.gsub!(/['\\]/, '\\\\\&') || text
1838    #end
1839
1840    def result(_binding=TOPLEVEL_BINDING)
1841      eval @src, _binding
1842    end
1843
1844    def evaluate(_context=Object.new)
1845      if _context.is_a?(Hash)
1846        _obj = Object.new
1847        _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
1848        _context = _obj
1849      end
1850      _context.instance_eval @src
1851    end
1852
1853  end
1854
1855
1856
1857  module PI
1858  end
1859
1860  class PI::TinyEruby
1861
1862    def initialize(input=nil, options={})
1863      @escape  = options[:escape] || 'Erubis::XmlHelper.escape_xml'
1864      @src = convert(input) if input
1865    end
1866
1867    attr_reader :src
1868
1869    EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m
1870
1871    def convert(input)
1872      src = "_buf = '';"           # preamble
1873      pos = 0
1874      input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr|
1875        match = Regexp.last_match
1876        len   = match.begin(0) - pos
1877        text  = input[pos, len]
1878        pos   = match.end(0)
1879        #src << " _buf << '" << escape_text(text) << "';"
1880        text.gsub!(/['\\]/, '\\\\\&')
1881        src << " _buf << '" << text << "';" unless text.empty?
1882        if stmt                # <?rb ... ?>
1883          if lspace && rspace
1884            src << "#{lspace}#{stmt}#{rspace}"
1885          else
1886            src << " _buf << '" << lspace << "';" if lspace
1887            src << stmt << ";"
1888            src << " _buf << '" << rspace << "';" if rspace
1889          end
1890        else                       # ${...}, $!{...}
1891          if !indicator
1892            src << " _buf << " << @escape << "(" << expr << ");"
1893          elsif indicator == '!'
1894            src << " _buf << (" << expr << ").to_s;"
1895          end
1896        end
1897      end
1898      #rest = $' || input                        # ruby1.8
1899      rest = pos == 0 ? input : input[pos..-1]   # ruby1.9
1900      #src << " _buf << '" << escape_text(rest) << "';"
1901      rest.gsub!(/['\\]/, '\\\\\&')
1902      src << " _buf << '" << rest << "';" unless rest.empty?
1903      src << "\n_buf.to_s\n"       # postamble
1904      return src
1905    end
1906
1907    #def escape_text(text)
1908    #  return text.gsub!(/['\\]/, '\\\\\&') || text
1909    #end
1910
1911    def result(_binding=TOPLEVEL_BINDING)
1912      eval @src, _binding
1913    end
1914
1915    def evaluate(_context=Object.new)
1916      if _context.is_a?(Hash)
1917        _obj = Object.new
1918        _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
1919        _context = _obj
1920      end
1921      _context.instance_eval @src
1922    end
1923
1924  end
1925
1926
1927end
1928#--end of require 'erubis/tiny'
1929#--begin of require 'erubis/engine/enhanced'
1930##
1931## $Release: 2.7.0 $
1932## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
1933##
1934
1935#--already included require 'erubis/enhancer'
1936#--already included require 'erubis/engine/eruby'
1937
1938
1939module Erubis
1940
1941
1942  #--
1943  ## moved to engine/ruby.rb
1944  #class EscapedEruby < Eruby
1945  #  include EscapeEnhancer
1946  #end
1947  #++
1948
1949
1950  #--
1951  ### (obsolete)
1952  #class FastEruby < Eruby
1953  #  include FastEnhancer
1954  #end
1955  #++
1956
1957
1958  class StdoutEruby < Eruby
1959    include StdoutEnhancer
1960  end
1961
1962
1963  class PrintOutEruby < Eruby
1964    include PrintOutEnhancer
1965  end
1966
1967
1968  class PrintEnabledEruby < Eruby
1969    include PrintEnabledEnhancer
1970  end
1971
1972
1973  class ArrayEruby < Eruby
1974    include ArrayEnhancer
1975  end
1976
1977
1978  class ArrayBufferEruby < Eruby
1979    include ArrayBufferEnhancer
1980  end
1981
1982
1983  class StringBufferEruby < Eruby
1984    include StringBufferEnhancer
1985  end
1986
1987
1988  class StringIOEruby < Eruby
1989    include StringIOEnhancer
1990  end
1991
1992
1993  class ErboutEruby < Eruby
1994    include ErboutEnhancer
1995  end
1996
1997
1998  class NoTextEruby < Eruby
1999    include NoTextEnhancer
2000  end
2001
2002
2003  class NoCodeEruby < Eruby
2004    include NoCodeEnhancer
2005  end
2006
2007
2008  class SimplifiedEruby < Eruby
2009    include SimplifyEnhancer
2010  end
2011
2012
2013  class StdoutSimplifiedEruby < Eruby
2014    include StdoutEnhancer
2015    include SimplifyEnhancer
2016  end
2017
2018
2019  class PrintOutSimplifiedEruby < Eruby
2020    include PrintOutEnhancer
2021    include SimplifyEnhancer
2022  end
2023
2024
2025  class BiPatternEruby < Eruby
2026    include BiPatternEnhancer
2027  end
2028
2029
2030  class PercentLineEruby < Eruby
2031    include PercentLineEnhancer
2032  end
2033
2034
2035  class PrefixedLineEruby < Eruby
2036    include PrefixedLineEnhancer
2037  end
2038
2039
2040  class HeaderFooterEruby < Eruby
2041    include HeaderFooterEnhancer
2042  end
2043
2044
2045  class DeleteIndentEruby < Eruby
2046    include DeleteIndentEnhancer
2047  end
2048
2049
2050  class InterpolationEruby < Eruby
2051    include InterpolationEnhancer
2052  end
2053
2054
2055end
2056#--end of require 'erubis/engine/enhanced'
2057#--begin of require 'erubis/engine/optimized'
2058##
2059## $Release: 2.7.0 $
2060## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
2061##
2062
2063
2064#--already included require 'erubis/engine/eruby'
2065
2066
2067module Erubis
2068
2069
2070  module OptimizedGenerator
2071    include Generator
2072
2073    def self.supported_properties()  # :nodoc:
2074      return []
2075    end
2076
2077    def init_generator(properties={})
2078      super
2079      @escapefunc ||= "Erubis::XmlHelper.escape_xml"
2080      @initialized = false
2081      @prev_is_expr = false
2082    end
2083
2084    protected
2085
2086    def escape_text(text)
2087      text.gsub(/['\\]/, '\\\\\&')   # "'" => "\\'",  '\\' => '\\\\'
2088    end
2089
2090    def escaped_expr(code)
2091      @escapefunc ||= 'Erubis::XmlHelper.escape_xml'
2092      return "#{@escapefunc}(#{code})"
2093    end
2094
2095    def switch_to_expr(src)
2096      return if @prev_is_expr
2097      @prev_is_expr = true
2098      src << ' _buf'
2099    end
2100
2101    def switch_to_stmt(src)
2102      return unless @prev_is_expr
2103      @prev_is_expr = false
2104      src << ';'
2105    end
2106
2107    def add_preamble(src)
2108      #@initialized = false
2109      #@prev_is_expr = false
2110    end
2111
2112    def add_text(src, text)
2113      return if text.empty?
2114      if @initialized
2115        switch_to_expr(src)
2116        src << " << '" << escape_text(text) << "'"
2117      else
2118        src << "_buf = '" << escape_text(text) << "';"
2119        @initialized = true
2120      end
2121    end
2122
2123    def add_stmt(src, code)
2124      switch_to_stmt(src) if @initialized
2125      #super
2126      src << code
2127      src << ';' unless code[-1] == ?\n
2128    end
2129
2130    def add_expr_literal(src, code)
2131      unless @initialized; src << "_buf = ''"; @initialized = true; end
2132      switch_to_expr(src)
2133      src << " << (" << code << ").to_s"
2134    end
2135
2136    def add_expr_escaped(src, code)
2137      unless @initialized; src << "_buf = ''"; @iniā€¦

Large files files are truncated, but you can click here to view the full file