PageRenderTime 62ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/18/erb.rb

http://github.com/rubinius/rubinius
Ruby | 862 lines | 444 code | 49 blank | 369 comment | 46 complexity | 101de318c16c509a80b0c1779f4aa0e3 MD5 | raw file
Possible License(s): BSD-3-Clause, MPL-2.0-no-copyleft-exception, 0BSD, GPL-2.0, LGPL-2.1
  1. # = ERB -- Ruby Templating
  2. #
  3. # Author:: Masatoshi SEKI
  4. # Documentation:: James Edward Gray II and Gavin Sinclair
  5. #
  6. # See ERB for primary documentation and ERB::Util for a couple of utility
  7. # routines.
  8. #
  9. # Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI
  10. #
  11. # You can redistribute it and/or modify it under the same terms as Ruby.
  12. #
  13. # = ERB -- Ruby Templating
  14. #
  15. # == Introduction
  16. #
  17. # ERB provides an easy to use but powerful templating system for Ruby. Using
  18. # ERB, actual Ruby code can be added to any plain text document for the
  19. # purposes of generating document information details and/or flow control.
  20. #
  21. # A very simple example is this:
  22. #
  23. # require 'erb'
  24. #
  25. # x = 42
  26. # template = ERB.new <<-EOF
  27. # The value of x is: <%= x %>
  28. # EOF
  29. # puts template.result(binding)
  30. #
  31. # <em>Prints:</em> The value of x is: 42
  32. #
  33. # More complex examples are given below.
  34. #
  35. #
  36. # == Recognized Tags
  37. #
  38. # ERB recognizes certain tags in the provided template and converts them based
  39. # on the rules below:
  40. #
  41. # <% Ruby code -- inline with output %>
  42. # <%= Ruby expression -- replace with result %>
  43. # <%# comment -- ignored -- useful in testing %>
  44. # % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
  45. # %% replaced with % if first thing on a line and % processing is used
  46. # <%% or %%> -- replace with <% or %> respectively
  47. #
  48. # All other text is passed through ERB filtering unchanged.
  49. #
  50. #
  51. # == Options
  52. #
  53. # There are several settings you can change when you use ERB:
  54. # * the nature of the tags that are recognized;
  55. # * the value of <tt>$SAFE</tt> under which the template is run;
  56. # * the binding used to resolve local variables in the template.
  57. #
  58. # See the ERB.new and ERB#result methods for more detail.
  59. #
  60. #
  61. # == Examples
  62. #
  63. # === Plain Text
  64. #
  65. # ERB is useful for any generic templating situation. Note that in this example, we use the
  66. # convenient "% at start of line" tag, and we quote the template literally with
  67. # <tt>%q{...}</tt> to avoid trouble with the backslash.
  68. #
  69. # require "erb"
  70. #
  71. # # Create template.
  72. # template = %q{
  73. # From: James Edward Gray II <james@grayproductions.net>
  74. # To: <%= to %>
  75. # Subject: Addressing Needs
  76. #
  77. # <%= to[/\w+/] %>:
  78. #
  79. # Just wanted to send a quick note assuring that your needs are being
  80. # addressed.
  81. #
  82. # I want you to know that my team will keep working on the issues,
  83. # especially:
  84. #
  85. # <%# ignore numerous minor requests -- focus on priorities %>
  86. # % priorities.each do |priority|
  87. # * <%= priority %>
  88. # % end
  89. #
  90. # Thanks for your patience.
  91. #
  92. # James Edward Gray II
  93. # }.gsub(/^ /, '')
  94. #
  95. # message = ERB.new(template, 0, "%<>")
  96. #
  97. # # Set up template data.
  98. # to = "Community Spokesman <spokesman@ruby_community.org>"
  99. # priorities = [ "Run Ruby Quiz",
  100. # "Document Modules",
  101. # "Answer Questions on Ruby Talk" ]
  102. #
  103. # # Produce result.
  104. # email = message.result
  105. # puts email
  106. #
  107. # <i>Generates:</i>
  108. #
  109. # From: James Edward Gray II <james@grayproductions.net>
  110. # To: Community Spokesman <spokesman@ruby_community.org>
  111. # Subject: Addressing Needs
  112. #
  113. # Community:
  114. #
  115. # Just wanted to send a quick note assuring that your needs are being addressed.
  116. #
  117. # I want you to know that my team will keep working on the issues, especially:
  118. #
  119. # * Run Ruby Quiz
  120. # * Document Modules
  121. # * Answer Questions on Ruby Talk
  122. #
  123. # Thanks for your patience.
  124. #
  125. # James Edward Gray II
  126. #
  127. # === Ruby in HTML
  128. #
  129. # ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby). Notice the need in
  130. # this example to provide a special binding when the template is run, so that the instance
  131. # variables in the Product object can be resolved.
  132. #
  133. # require "erb"
  134. #
  135. # # Build template data class.
  136. # class Product
  137. # def initialize( code, name, desc, cost )
  138. # @code = code
  139. # @name = name
  140. # @desc = desc
  141. # @cost = cost
  142. #
  143. # @features = [ ]
  144. # end
  145. #
  146. # def add_feature( feature )
  147. # @features << feature
  148. # end
  149. #
  150. # # Support templating of member data.
  151. # def get_binding
  152. # binding
  153. # end
  154. #
  155. # # ...
  156. # end
  157. #
  158. # # Create template.
  159. # template = %{
  160. # <html>
  161. # <head><title>Ruby Toys -- <%= @name %></title></head>
  162. # <body>
  163. #
  164. # <h1><%= @name %> (<%= @code %>)</h1>
  165. # <p><%= @desc %></p>
  166. #
  167. # <ul>
  168. # <% @features.each do |f| %>
  169. # <li><b><%= f %></b></li>
  170. # <% end %>
  171. # </ul>
  172. #
  173. # <p>
  174. # <% if @cost < 10 %>
  175. # <b>Only <%= @cost %>!!!</b>
  176. # <% else %>
  177. # Call for a price, today!
  178. # <% end %>
  179. # </p>
  180. #
  181. # </body>
  182. # </html>
  183. # }.gsub(/^ /, '')
  184. #
  185. # rhtml = ERB.new(template)
  186. #
  187. # # Set up template data.
  188. # toy = Product.new( "TZ-1002",
  189. # "Rubysapien",
  190. # "Geek's Best Friend! Responds to Ruby commands...",
  191. # 999.95 )
  192. # toy.add_feature("Listens for verbal commands in the Ruby language!")
  193. # toy.add_feature("Ignores Perl, Java, and all C variants.")
  194. # toy.add_feature("Karate-Chop Action!!!")
  195. # toy.add_feature("Matz signature on left leg.")
  196. # toy.add_feature("Gem studded eyes... Rubies, of course!")
  197. #
  198. # # Produce result.
  199. # rhtml.run(toy.get_binding)
  200. #
  201. # <i>Generates (some blank lines removed):</i>
  202. #
  203. # <html>
  204. # <head><title>Ruby Toys -- Rubysapien</title></head>
  205. # <body>
  206. #
  207. # <h1>Rubysapien (TZ-1002)</h1>
  208. # <p>Geek's Best Friend! Responds to Ruby commands...</p>
  209. #
  210. # <ul>
  211. # <li><b>Listens for verbal commands in the Ruby language!</b></li>
  212. # <li><b>Ignores Perl, Java, and all C variants.</b></li>
  213. # <li><b>Karate-Chop Action!!!</b></li>
  214. # <li><b>Matz signature on left leg.</b></li>
  215. # <li><b>Gem studded eyes... Rubies, of course!</b></li>
  216. # </ul>
  217. #
  218. # <p>
  219. # Call for a price, today!
  220. # </p>
  221. #
  222. # </body>
  223. # </html>
  224. #
  225. #
  226. # == Notes
  227. #
  228. # There are a variety of templating solutions available in various Ruby projects:
  229. # * ERB's big brother, eRuby, works the same but is written in C for speed;
  230. # * Amrita (smart at producing HTML/XML);
  231. # * cs/Template (written in C for speed);
  232. # * RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
  233. # * and others; search the RAA.
  234. #
  235. # Rails, the web application framework, uses ERB to create views.
  236. #
  237. class ERB
  238. Revision = '$Date: 2009-02-23 09:44:50 -0800 (Mon, 23 Feb 2009) $' #'
  239. # Returns revision information for the erb.rb module.
  240. def self.version
  241. "erb.rb [2.1.0 #{ERB::Revision.split[1]}]"
  242. end
  243. end
  244. #--
  245. # ERB::Compiler
  246. class ERB
  247. class Compiler # :nodoc:
  248. class PercentLine # :nodoc:
  249. def initialize(str)
  250. @value = str
  251. end
  252. attr_reader :value
  253. alias :to_s :value
  254. def empty?
  255. @value.empty?
  256. end
  257. end
  258. class Scanner # :nodoc:
  259. @scanner_map = {}
  260. def self.regist_scanner(klass, trim_mode, percent)
  261. @scanner_map[[trim_mode, percent]] = klass
  262. end
  263. def self.default_scanner=(klass)
  264. @default_scanner = klass
  265. end
  266. def self.make_scanner(src, trim_mode, percent)
  267. klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
  268. klass.new(src, trim_mode, percent)
  269. end
  270. def initialize(src, trim_mode, percent)
  271. @src = src
  272. @stag = nil
  273. end
  274. attr_accessor :stag
  275. def scan; end
  276. end
  277. class TrimScanner < Scanner # :nodoc:
  278. def initialize(src, trim_mode, percent)
  279. super
  280. @trim_mode = trim_mode
  281. @percent = percent
  282. if @trim_mode == '>'
  283. @scan_line = self.method(:trim_line1)
  284. elsif @trim_mode == '<>'
  285. @scan_line = self.method(:trim_line2)
  286. elsif @trim_mode == '-'
  287. @scan_line = self.method(:explicit_trim_line)
  288. else
  289. @scan_line = self.method(:scan_line)
  290. end
  291. end
  292. attr_accessor :stag
  293. def scan(&block)
  294. @stag = nil
  295. if @percent
  296. @src.each do |line|
  297. percent_line(line, &block)
  298. end
  299. else
  300. @scan_line.call(@src, &block)
  301. end
  302. nil
  303. end
  304. def percent_line(line, &block)
  305. if @stag || line[0] != ?%
  306. return @scan_line.call(line, &block)
  307. end
  308. line[0] = ''
  309. if line[0] == ?%
  310. @scan_line.call(line, &block)
  311. else
  312. yield(PercentLine.new(line.chomp))
  313. end
  314. end
  315. def scan_line(line)
  316. line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
  317. tokens.each do |token|
  318. next if token.empty?
  319. yield(token)
  320. end
  321. end
  322. end
  323. def trim_line1(line)
  324. line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
  325. tokens.each do |token|
  326. next if token.empty?
  327. if token == "%>\n"
  328. yield('%>')
  329. yield(:cr)
  330. else
  331. yield(token)
  332. end
  333. end
  334. end
  335. end
  336. def trim_line2(line)
  337. head = nil
  338. line.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
  339. tokens.each do |token|
  340. next if token.empty?
  341. head = token unless head
  342. if token == "%>\n"
  343. yield('%>')
  344. if is_erb_stag?(head)
  345. yield(:cr)
  346. else
  347. yield("\n")
  348. end
  349. head = nil
  350. else
  351. yield(token)
  352. head = nil if token == "\n"
  353. end
  354. end
  355. end
  356. end
  357. def explicit_trim_line(line)
  358. line.scan(/(.*?)(^[ \t]*<%\-|<%\-|<%%|%%>|<%=|<%#|<%|-%>\n|-%>|%>|\z)/m) do |tokens|
  359. tokens.each do |token|
  360. next if token.empty?
  361. if @stag.nil? && /[ \t]*<%-/ =~ token
  362. yield('<%')
  363. elsif @stag && token == "-%>\n"
  364. yield('%>')
  365. yield(:cr)
  366. elsif @stag && token == '-%>'
  367. yield('%>')
  368. else
  369. yield(token)
  370. end
  371. end
  372. end
  373. end
  374. ERB_STAG = %w(<%= <%# <%)
  375. def is_erb_stag?(s)
  376. ERB_STAG.member?(s)
  377. end
  378. end
  379. Scanner.default_scanner = TrimScanner
  380. class SimpleScanner < Scanner # :nodoc:
  381. def scan
  382. @src.scan(/(.*?)(<%%|%%>|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
  383. tokens.each do |token|
  384. next if token.empty?
  385. yield(token)
  386. end
  387. end
  388. end
  389. end
  390. Scanner.regist_scanner(SimpleScanner, nil, false)
  391. begin
  392. require 'strscan'
  393. class SimpleScanner2 < Scanner # :nodoc:
  394. def scan
  395. stag_reg = /(.*?)(<%%|<%=|<%#|<%|\z)/m
  396. etag_reg = /(.*?)(%%>|%>|\z)/m
  397. scanner = StringScanner.new(@src)
  398. while ! scanner.eos?
  399. scanner.scan(@stag ? etag_reg : stag_reg)
  400. yield(scanner[1])
  401. yield(scanner[2])
  402. end
  403. end
  404. end
  405. Scanner.regist_scanner(SimpleScanner2, nil, false)
  406. class ExplicitScanner < Scanner # :nodoc:
  407. def scan
  408. stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%=|<%#|<%-|<%|\z)/m
  409. etag_reg = /(.*?)(%%>|-%>|%>|\z)/m
  410. scanner = StringScanner.new(@src)
  411. while ! scanner.eos?
  412. scanner.scan(@stag ? etag_reg : stag_reg)
  413. yield(scanner[1])
  414. elem = scanner[2]
  415. if /[ \t]*<%-/ =~ elem
  416. yield('<%')
  417. elsif elem == '-%>'
  418. yield('%>')
  419. yield(:cr) if scanner.scan(/(\n|\z)/)
  420. else
  421. yield(elem)
  422. end
  423. end
  424. end
  425. end
  426. Scanner.regist_scanner(ExplicitScanner, '-', false)
  427. rescue LoadError
  428. end
  429. class Buffer # :nodoc:
  430. def initialize(compiler)
  431. @compiler = compiler
  432. @line = []
  433. @script = ""
  434. @compiler.pre_cmd.each do |x|
  435. push(x)
  436. end
  437. end
  438. attr_reader :script
  439. def push(cmd)
  440. @line << cmd
  441. end
  442. def cr
  443. @script << (@line.join('; '))
  444. @line = []
  445. @script << "\n"
  446. end
  447. def close
  448. return unless @line
  449. @compiler.post_cmd.each do |x|
  450. push(x)
  451. end
  452. @script << (@line.join('; '))
  453. @line = nil
  454. end
  455. end
  456. def content_dump(s)
  457. n = s.count("\n")
  458. if n > 0
  459. s.dump + "\n" * n
  460. else
  461. s.dump
  462. end
  463. end
  464. def compile(s)
  465. out = Buffer.new(self)
  466. content = ''
  467. scanner = make_scanner(s)
  468. scanner.scan do |token|
  469. next if token.nil?
  470. next if token == ''
  471. if scanner.stag.nil?
  472. case token
  473. when PercentLine
  474. out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
  475. content = ''
  476. out.push(token.to_s)
  477. out.cr
  478. when :cr
  479. out.cr
  480. when '<%', '<%=', '<%#'
  481. scanner.stag = token
  482. out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
  483. content = ''
  484. when "\n"
  485. content << "\n"
  486. out.push("#{@put_cmd} #{content_dump(content)}")
  487. content = ''
  488. when '<%%'
  489. content << '<%'
  490. else
  491. content << token
  492. end
  493. else
  494. case token
  495. when '%>'
  496. case scanner.stag
  497. when '<%'
  498. if content[-1] == ?\n
  499. content.chop!
  500. out.push(content)
  501. out.cr
  502. else
  503. out.push(content)
  504. end
  505. when '<%='
  506. out.push("#{@insert_cmd}((#{content}).to_s)")
  507. when '<%#'
  508. # out.push("# #{content_dump(content)}")
  509. end
  510. scanner.stag = nil
  511. content = ''
  512. when '%%>'
  513. content << '%>'
  514. else
  515. content << token
  516. end
  517. end
  518. end
  519. out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
  520. out.close
  521. out.script
  522. end
  523. def prepare_trim_mode(mode)
  524. case mode
  525. when 1
  526. return [false, '>']
  527. when 2
  528. return [false, '<>']
  529. when 0
  530. return [false, nil]
  531. when String
  532. perc = mode.include?('%')
  533. if mode.include?('-')
  534. return [perc, '-']
  535. elsif mode.include?('<>')
  536. return [perc, '<>']
  537. elsif mode.include?('>')
  538. return [perc, '>']
  539. else
  540. [perc, nil]
  541. end
  542. else
  543. return [false, nil]
  544. end
  545. end
  546. def make_scanner(src)
  547. Scanner.make_scanner(src, @trim_mode, @percent)
  548. end
  549. def initialize(trim_mode)
  550. @percent, @trim_mode = prepare_trim_mode(trim_mode)
  551. @put_cmd = 'print'
  552. @insert_cmd = @put_cmd
  553. @pre_cmd = []
  554. @post_cmd = []
  555. end
  556. attr_reader :percent, :trim_mode
  557. attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
  558. end
  559. end
  560. #--
  561. # ERB
  562. class ERB
  563. #
  564. # Constructs a new ERB object with the template specified in _str_.
  565. #
  566. # An ERB object works by building a chunk of Ruby code that will output
  567. # the completed template when run. If _safe_level_ is set to a non-nil value,
  568. # ERB code will be run in a separate thread with <b>$SAFE</b> set to the
  569. # provided level.
  570. #
  571. # If _trim_mode_ is passed a String containing one or more of the following
  572. # modifiers, ERB will adjust its code generation as listed:
  573. #
  574. # % enables Ruby code processing for lines beginning with %
  575. # <> omit newline for lines starting with <% and ending in %>
  576. # > omit newline for lines ending in %>
  577. #
  578. # _eoutvar_ can be used to set the name of the variable ERB will build up
  579. # its output in. This is useful when you need to run multiple ERB
  580. # templates through the same binding and/or when you want to control where
  581. # output ends up. Pass the name of the variable to be used inside a String.
  582. #
  583. # === Example
  584. #
  585. # require "erb"
  586. #
  587. # # build data class
  588. # class Listings
  589. # PRODUCT = { :name => "Chicken Fried Steak",
  590. # :desc => "A well messages pattie, breaded and fried.",
  591. # :cost => 9.95 }
  592. #
  593. # attr_reader :product, :price
  594. #
  595. # def initialize( product = "", price = "" )
  596. # @product = product
  597. # @price = price
  598. # end
  599. #
  600. # def build
  601. # b = binding
  602. # # create and run templates, filling member data variables
  603. # ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b
  604. # <%= PRODUCT[:name] %>
  605. # <%= PRODUCT[:desc] %>
  606. # END_PRODUCT
  607. # ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b
  608. # <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
  609. # <%= PRODUCT[:desc] %>
  610. # END_PRICE
  611. # end
  612. # end
  613. #
  614. # # setup template data
  615. # listings = Listings.new
  616. # listings.build
  617. #
  618. # puts listings.product + "\n" + listings.price
  619. #
  620. # _Generates_
  621. #
  622. # Chicken Fried Steak
  623. # A well messages pattie, breaded and fried.
  624. #
  625. # Chicken Fried Steak -- 9.95
  626. # A well messages pattie, breaded and fried.
  627. #
  628. def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
  629. @safe_level = safe_level
  630. compiler = ERB::Compiler.new(trim_mode)
  631. set_eoutvar(compiler, eoutvar)
  632. @src = compiler.compile(str)
  633. @filename = nil
  634. end
  635. # The Ruby code generated by ERB
  636. attr_reader :src
  637. # The optional _filename_ argument passed to Kernel#eval when the ERB code
  638. # is run
  639. attr_accessor :filename
  640. #
  641. # Can be used to set _eoutvar_ as described in ERB#new. It's probably easier
  642. # to just use the constructor though, since calling this method requires the
  643. # setup of an ERB _compiler_ object.
  644. #
  645. def set_eoutvar(compiler, eoutvar = '_erbout')
  646. compiler.put_cmd = "#{eoutvar}.concat"
  647. compiler.insert_cmd = "#{eoutvar}.concat"
  648. cmd = []
  649. cmd.push "#{eoutvar} = ''"
  650. compiler.pre_cmd = cmd
  651. cmd = []
  652. cmd.push(eoutvar)
  653. compiler.post_cmd = cmd
  654. end
  655. # Generate results and print them. (see ERB#result)
  656. def run(b=TOPLEVEL_BINDING)
  657. print self.result(b)
  658. end
  659. #
  660. # Executes the generated ERB code to produce a completed template, returning
  661. # the results of that code. (See ERB#new for details on how this process can
  662. # be affected by _safe_level_.)
  663. #
  664. # _b_ accepts a Binding or Proc object which is used to set the context of
  665. # code evaluation.
  666. #
  667. def result(b=TOPLEVEL_BINDING)
  668. if @safe_level
  669. proc {
  670. $SAFE = @safe_level
  671. eval(@src, b, (@filename || '(erb)'), 1)
  672. }.call
  673. else
  674. eval(@src, b, (@filename || '(erb)'), 1)
  675. end
  676. end
  677. # Define _methodname_ as instance method of _mod_ from compiled ruby source.
  678. #
  679. # example:
  680. # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
  681. # erb = ERB.new(File.read(filename))
  682. # erb.def_method(MyClass, 'render(arg1, arg2)', filename)
  683. # print MyClass.new.render('foo', 123)
  684. def def_method(mod, methodname, fname='(ERB)')
  685. mod.module_eval("def #{methodname}\n" + self.src + "\nend\n", fname, 0)
  686. end
  687. # Create unnamed module, define _methodname_ as instance method of it, and return it.
  688. #
  689. # example:
  690. # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
  691. # erb = ERB.new(File.read(filename))
  692. # erb.filename = filename
  693. # MyModule = erb.def_module('render(arg1, arg2)')
  694. # class MyClass
  695. # include MyModule
  696. # end
  697. def def_module(methodname='erb')
  698. mod = Module.new
  699. def_method(mod, methodname, @filename || '(ERB)')
  700. mod
  701. end
  702. # Define unnamed class which has _methodname_ as instance method, and return it.
  703. #
  704. # example:
  705. # class MyClass_
  706. # def initialize(arg1, arg2)
  707. # @arg1 = arg1; @arg2 = arg2
  708. # end
  709. # end
  710. # filename = 'example.rhtml' # @arg1 and @arg2 are used in example.rhtml
  711. # erb = ERB.new(File.read(filename))
  712. # erb.filename = filename
  713. # MyClass = erb.def_class(MyClass_, 'render()')
  714. # print MyClass.new('foo', 123).render()
  715. def def_class(superklass=Object, methodname='result')
  716. cls = Class.new(superklass)
  717. def_method(cls, methodname, @filename || '(ERB)')
  718. cls
  719. end
  720. end
  721. #--
  722. # ERB::Util
  723. class ERB
  724. # A utility module for conversion routines, often handy in HTML generation.
  725. module Util
  726. public
  727. #
  728. # A utility method for escaping HTML tag characters in _s_.
  729. #
  730. # require "erb"
  731. # include ERB::Util
  732. #
  733. # puts html_escape("is a > 0 & a < 10?")
  734. #
  735. # _Generates_
  736. #
  737. # is a &gt; 0 &amp; a &lt; 10?
  738. #
  739. def html_escape(s)
  740. s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
  741. end
  742. alias h html_escape
  743. module_function :h
  744. module_function :html_escape
  745. #
  746. # A utility method for encoding the String _s_ as a URL.
  747. #
  748. # require "erb"
  749. # include ERB::Util
  750. #
  751. # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
  752. #
  753. # _Generates_
  754. #
  755. # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
  756. #
  757. def url_encode(s)
  758. s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
  759. end
  760. alias u url_encode
  761. module_function :u
  762. module_function :url_encode
  763. end
  764. end
  765. #--
  766. # ERB::DefMethod
  767. class ERB
  768. # Utility module to define eRuby script as instance method.
  769. #
  770. # === Example
  771. #
  772. # example.rhtml:
  773. # <% for item in @items %>
  774. # <b><%= item %></b>
  775. # <% end %>
  776. #
  777. # example.rb:
  778. # require 'erb'
  779. # class MyClass
  780. # extend ERB::DefMethod
  781. # def_erb_method('render()', 'example.rhtml')
  782. # def initialize(items)
  783. # @items = items
  784. # end
  785. # end
  786. # print MyClass.new([10,20,30]).render()
  787. #
  788. # result:
  789. #
  790. # <b>10</b>
  791. #
  792. # <b>20</b>
  793. #
  794. # <b>30</b>
  795. #
  796. module DefMethod
  797. public
  798. # define _methodname_ as instance method of current module, using ERB object or eRuby file
  799. def def_erb_method(methodname, erb_or_fname)
  800. if erb_or_fname.kind_of? String
  801. fname = erb_or_fname
  802. erb = ERB.new(File.read(fname))
  803. erb.def_method(self, methodname, fname)
  804. else
  805. erb = erb_or_fname
  806. erb.def_method(self, methodname, erb.filename || '(ERB)')
  807. end
  808. end
  809. module_function :def_erb_method
  810. end
  811. end