PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/External.LCA_RESTRICTED/Languages/Ruby/ruby19/lib/ruby/gems/1.9.1/gems/erubis-2.6.6/contrib/erubis

http://github.com/IronLanguages/main
Ruby | 3330 lines | 1932 code | 614 blank | 784 comment | 276 complexity | 02f7cd7e95faaa90def31c2c42c06c8a MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

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

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

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