tiny.rb 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. ##
  2. ## $Release: 2.7.0 $
  3. ## copyright(c) 2006-2011 kuwata-lab.com all rights reserved.
  4. ##
  5. module Erubis
  6. ##
  7. ## tiny and the simplest implementation of eRuby
  8. ##
  9. ## ex.
  10. ## eruby = TinyEruby.new(File.read('example.rhtml'))
  11. ## print eruby.src # print ruby code
  12. ## print eruby.result(binding()) # eval ruby code with Binding object
  13. ## print eruby.evalute(context) # eval ruby code with context object
  14. ##
  15. class TinyEruby
  16. def initialize(input=nil)
  17. @src = convert(input) if input
  18. end
  19. attr_reader :src
  20. EMBEDDED_PATTERN = /<%(=+|\#)?(.*?)-?%>/m
  21. def convert(input)
  22. src = "_buf = '';" # preamble
  23. pos = 0
  24. input.scan(EMBEDDED_PATTERN) do |indicator, code|
  25. m = Regexp.last_match
  26. text = input[pos...m.begin(0)]
  27. pos = m.end(0)
  28. #src << " _buf << '" << escape_text(text) << "';"
  29. text.gsub!(/['\\]/, '\\\\\&')
  30. src << " _buf << '" << text << "';" unless text.empty?
  31. if !indicator # <% %>
  32. src << code << ";"
  33. elsif indicator == '#' # <%# %>
  34. src << ("\n" * code.count("\n"))
  35. else # <%= %>
  36. src << " _buf << (" << code << ").to_s;"
  37. end
  38. end
  39. #rest = $' || input # ruby1.8
  40. rest = pos == 0 ? input : input[pos..-1] # ruby1.9
  41. #src << " _buf << '" << escape_text(rest) << "';"
  42. rest.gsub!(/['\\]/, '\\\\\&')
  43. src << " _buf << '" << rest << "';" unless rest.empty?
  44. src << "\n_buf.to_s\n" # postamble
  45. return src
  46. end
  47. #def escape_text(text)
  48. # return text.gsub!(/['\\]/, '\\\\\&') || text
  49. #end
  50. def result(_binding=TOPLEVEL_BINDING)
  51. eval @src, _binding
  52. end
  53. def evaluate(_context=Object.new)
  54. if _context.is_a?(Hash)
  55. _obj = Object.new
  56. _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
  57. _context = _obj
  58. end
  59. _context.instance_eval @src
  60. end
  61. end
  62. module PI
  63. end
  64. class PI::TinyEruby
  65. def initialize(input=nil, options={})
  66. @escape = options[:escape] || 'Erubis::XmlHelper.escape_xml'
  67. @src = convert(input) if input
  68. end
  69. attr_reader :src
  70. EMBEDDED_PATTERN = /(^[ \t]*)?<\?rb(\s.*?)\?>([ \t]*\r?\n)?|@(!+)?\{(.*?)\}@/m
  71. def convert(input)
  72. src = "_buf = '';" # preamble
  73. pos = 0
  74. input.scan(EMBEDDED_PATTERN) do |lspace, stmt, rspace, indicator, expr|
  75. match = Regexp.last_match
  76. len = match.begin(0) - pos
  77. text = input[pos, len]
  78. pos = match.end(0)
  79. #src << " _buf << '" << escape_text(text) << "';"
  80. text.gsub!(/['\\]/, '\\\\\&')
  81. src << " _buf << '" << text << "';" unless text.empty?
  82. if stmt # <?rb ... ?>
  83. if lspace && rspace
  84. src << "#{lspace}#{stmt}#{rspace}"
  85. else
  86. src << " _buf << '" << lspace << "';" if lspace
  87. src << stmt << ";"
  88. src << " _buf << '" << rspace << "';" if rspace
  89. end
  90. else # ${...}, $!{...}
  91. if !indicator
  92. src << " _buf << " << @escape << "(" << expr << ");"
  93. elsif indicator == '!'
  94. src << " _buf << (" << expr << ").to_s;"
  95. end
  96. end
  97. end
  98. #rest = $' || input # ruby1.8
  99. rest = pos == 0 ? input : input[pos..-1] # ruby1.9
  100. #src << " _buf << '" << escape_text(rest) << "';"
  101. rest.gsub!(/['\\]/, '\\\\\&')
  102. src << " _buf << '" << rest << "';" unless rest.empty?
  103. src << "\n_buf.to_s\n" # postamble
  104. return src
  105. end
  106. #def escape_text(text)
  107. # return text.gsub!(/['\\]/, '\\\\\&') || text
  108. #end
  109. def result(_binding=TOPLEVEL_BINDING)
  110. eval @src, _binding
  111. end
  112. def evaluate(_context=Object.new)
  113. if _context.is_a?(Hash)
  114. _obj = Object.new
  115. _context.each do |k, v| _obj.instance_variable_set("@#{k}", v) end
  116. _context = _obj
  117. end
  118. _context.instance_eval @src
  119. end
  120. end
  121. end