123456789_123456789_123456789_123456789_123456789_

Class: ERB::Compiler

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
Inherits: Object
Defined in: lib/erb/compiler.rb

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(trim_mode) ⇒ Compiler

Construct a new compiler using the trim_mode. See ERB.new for available trim modes.

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 427

def initialize(trim_mode)
  @percent, @trim_mode = prepare_trim_mode(trim_mode)
  @put_cmd = 'print'
  @insert_cmd = @put_cmd
  @pre_cmd = []
  @post_cmd = []
end

Instance Attribute Details

#content (rw, private)

A buffered text in #compile

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 451

attr_accessor :content

#insert_cmd (rw)

The command to handle text that is inserted prior to a newline

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 440

attr_accessor :insert_cmd

#percent (readonly)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 434

attr_reader :percent, :trim_mode

#post_cmd (rw)

An array of commands appended to compiled code

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 446

attr_accessor :post_cmd

#pre_cmd (rw)

An array of commands prepended to compiled code

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 443

attr_accessor :pre_cmd

#put_cmd (rw)

The command to handle text that ends with a newline

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 437

attr_accessor :put_cmd

#trim_mode (readonly)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 434

attr_reader :percent, :trim_mode

Instance Method Details

#add_insert_cmd(out, content)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 309

def add_insert_cmd(out, content)
  out.push("#{@insert_cmd}((#{content}).to_s)")
end

#add_put_cmd(out, content)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 305

def add_put_cmd(out, content)
  out.push("#{@put_cmd} #{content.dump}.freeze#{"\n" * content.count("\n")}")
end

#compile(s)

Compiles an ::ERB template into Ruby code. Returns an array of the code and encoding like [“code”, Encoding].

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 315

def compile(s)
  enc = s.encoding
  raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
  s = s.b # see String#b
  magic_comment = detect_magic_comment(s, enc)
  out = Buffer.new(self, *magic_comment)

  self.content = +''
  scanner = make_scanner(s)
  scanner.scan do |token|
    next if token.nil?
    next if token == ''
    if scanner.stag.nil?
      compile_stag(token, out, scanner)
    else
      compile_etag(token, out, scanner)
    end
  end
  add_put_cmd(out, content) if content.size > 0
  out.close
  return out.script, *magic_comment
end

#compile_content(stag, out)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 375

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("\n" * content.count("\n")) # only adjust lineno
  end
end

#compile_etag(etag, out, scanner)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 362

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

#compile_stag(stag, out, scanner)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 338

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

#detect_magic_comment(s, enc = nil) (private)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 453

def detect_magic_comment(s, enc = nil)
  re = @percent ? /\G(?:<%#(.*)%>|%#(.*)\n)/ : /\G<%#(.*)%>/
  frozen = nil
  s.scan(re) do
    comment = $+
    comment = $1 if comment[/-\*-\s*([^\s].*?)\s*-\*-$/]
    case comment
    when %r"coding\s*[=:]\s*([[:alnum:]\-_]+)"
      enc = Encoding.find($1.sub(/-(?:mac|dos|unix)/i, ''))
    when %r"frozen[-_]string[-_]literal\s*:\s*([[:alnum:]]+)"
      frozen = $1
    end
  end
  return enc, frozen
end

#make_scanner(src)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 421

def make_scanner(src) # :nodoc:
  Scanner.make_scanner(src, @trim_mode, @percent)
end

#prepare_trim_mode(mode)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 392

def prepare_trim_mode(mode) # :nodoc:
  case mode
  when 1
    return [false, '>']
  when 2
    return [false, '<>']
  when 0, nil
    return [false, nil]
  when String
    unless mode.match?(/\A(%|-|>|<>){1,2}\z/)
      warn_invalid_trim_mode(mode, uplevel: 5)
    end

    perc = mode.include?('%')
    if mode.include?('-')
      return [perc, '-']
    elsif mode.include?('<>')
      return [perc, '<>']
    elsif mode.include?('>')
      return [perc, '>']
    else
      [perc, nil]
    end
  else
    warn_invalid_trim_mode(mode, uplevel: 5)
    return [false, nil]
  end
end

#warn_invalid_trim_mode(mode, uplevel:) (private)

[ GitHub ]

  
# File 'lib/erb/compiler.rb', line 469

def warn_invalid_trim_mode(mode, uplevel:)
  warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
end