[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / lib / erb.rb
blobbc1615d7da6e6d8ee65dd60d072350b185496bec
1 # -*- coding: us-ascii -*-
2 # frozen_string_literal: true
3 # = ERB -- Ruby Templating
5 # Author:: Masatoshi SEKI
6 # Documentation:: James Edward Gray II, Gavin Sinclair, and Simon Chiang
8 # See ERB for primary documentation and ERB::Util for a couple of utility
9 # routines.
11 # Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI
13 # You can redistribute it and/or modify it under the same terms as Ruby.
15 require 'cgi/util'
16 require 'erb/version'
17 require 'erb/compiler'
18 require 'erb/def_method'
19 require 'erb/util'
22 # = ERB -- Ruby Templating
24 # == Introduction
26 # ERB provides an easy to use but powerful templating system for Ruby.  Using
27 # ERB, actual Ruby code can be added to any plain text document for the
28 # purposes of generating document information details and/or flow control.
30 # A very simple example is this:
32 #   require 'erb'
34 #   x = 42
35 #   template = ERB.new <<-EOF
36 #     The value of x is: <%= x %>
37 #   EOF
38 #   puts template.result(binding)
40 # <em>Prints:</em> The value of x is: 42
42 # More complex examples are given below.
45 # == Recognized Tags
47 # ERB recognizes certain tags in the provided template and converts them based
48 # on the rules below:
50 #   <% Ruby code -- inline with output %>
51 #   <%= Ruby expression -- replace with result %>
52 #   <%# comment -- ignored -- useful in testing %> (`<% #` doesn't work. Don't use Ruby comments.)
53 #   % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
54 #   %% replaced with % if first thing on a line and % processing is used
55 #   <%% or %%> -- replace with <% or %> respectively
57 # All other text is passed through ERB filtering unchanged.
60 # == Options
62 # There are several settings you can change when you use ERB:
63 # * the nature of the tags that are recognized;
64 # * the binding used to resolve local variables in the template.
66 # See the ERB.new and ERB#result methods for more detail.
68 # == Character encodings
70 # ERB (or Ruby code generated by ERB) returns a string in the same
71 # character encoding as the input string.  When the input string has
72 # a magic comment, however, it returns a string in the encoding specified
73 # by the magic comment.
75 #   # -*- coding: utf-8 -*-
76 #   require 'erb'
78 #   template = ERB.new <<EOF
79 #   <%#-*- coding: Big5 -*-%>
80 #     \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
81 #   EOF
82 #   puts template.result
84 # <em>Prints:</em> \_\_ENCODING\_\_ is Big5.
87 # == Examples
89 # === Plain Text
91 # ERB is useful for any generic templating situation.  Note that in this example, we use the
92 # convenient "% at start of line" tag, and we quote the template literally with
93 # <tt>%q{...}</tt> to avoid trouble with the backslash.
95 #   require "erb"
97 #   # Create template.
98 #   template = %q{
99 #     From:  James Edward Gray II <james@grayproductions.net>
100 #     To:  <%= to %>
101 #     Subject:  Addressing Needs
103 #     <%= to[/\w+/] %>:
105 #     Just wanted to send a quick note assuring that your needs are being
106 #     addressed.
108 #     I want you to know that my team will keep working on the issues,
109 #     especially:
111 #     <%# ignore numerous minor requests -- focus on priorities %>
112 #     % priorities.each do |priority|
113 #       * <%= priority %>
114 #     % end
116 #     Thanks for your patience.
118 #     James Edward Gray II
119 #   }.gsub(/^  /, '')
121 #   message = ERB.new(template, trim_mode: "%<>")
123 #   # Set up template data.
124 #   to = "Community Spokesman <spokesman@ruby_community.org>"
125 #   priorities = [ "Run Ruby Quiz",
126 #                  "Document Modules",
127 #                  "Answer Questions on Ruby Talk" ]
129 #   # Produce result.
130 #   email = message.result
131 #   puts email
133 # <i>Generates:</i>
135 #   From:  James Edward Gray II <james@grayproductions.net>
136 #   To:  Community Spokesman <spokesman@ruby_community.org>
137 #   Subject:  Addressing Needs
139 #   Community:
141 #   Just wanted to send a quick note assuring that your needs are being addressed.
143 #   I want you to know that my team will keep working on the issues, especially:
145 #       * Run Ruby Quiz
146 #       * Document Modules
147 #       * Answer Questions on Ruby Talk
149 #   Thanks for your patience.
151 #   James Edward Gray II
153 # === Ruby in HTML
155 # ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby).  Notice the need in
156 # this example to provide a special binding when the template is run, so that the instance
157 # variables in the Product object can be resolved.
159 #   require "erb"
161 #   # Build template data class.
162 #   class Product
163 #     def initialize( code, name, desc, cost )
164 #       @code = code
165 #       @name = name
166 #       @desc = desc
167 #       @cost = cost
169 #       @features = [ ]
170 #     end
172 #     def add_feature( feature )
173 #       @features << feature
174 #     end
176 #     # Support templating of member data.
177 #     def get_binding
178 #       binding
179 #     end
181 #     # ...
182 #   end
184 #   # Create template.
185 #   template = %{
186 #     <html>
187 #       <head><title>Ruby Toys -- <%= @name %></title></head>
188 #       <body>
190 #         <h1><%= @name %> (<%= @code %>)</h1>
191 #         <p><%= @desc %></p>
193 #         <ul>
194 #           <% @features.each do |f| %>
195 #             <li><b><%= f %></b></li>
196 #           <% end %>
197 #         </ul>
199 #         <p>
200 #           <% if @cost < 10 %>
201 #             <b>Only <%= @cost %>!!!</b>
202 #           <% else %>
203 #              Call for a price, today!
204 #           <% end %>
205 #         </p>
207 #       </body>
208 #     </html>
209 #   }.gsub(/^  /, '')
211 #   rhtml = ERB.new(template)
213 #   # Set up template data.
214 #   toy = Product.new( "TZ-1002",
215 #                      "Rubysapien",
216 #                      "Geek's Best Friend!  Responds to Ruby commands...",
217 #                      999.95 )
218 #   toy.add_feature("Listens for verbal commands in the Ruby language!")
219 #   toy.add_feature("Ignores Perl, Java, and all C variants.")
220 #   toy.add_feature("Karate-Chop Action!!!")
221 #   toy.add_feature("Matz signature on left leg.")
222 #   toy.add_feature("Gem studded eyes... Rubies, of course!")
224 #   # Produce result.
225 #   rhtml.run(toy.get_binding)
227 # <i>Generates (some blank lines removed):</i>
229 #    <html>
230 #      <head><title>Ruby Toys -- Rubysapien</title></head>
231 #      <body>
233 #        <h1>Rubysapien (TZ-1002)</h1>
234 #        <p>Geek's Best Friend!  Responds to Ruby commands...</p>
236 #        <ul>
237 #            <li><b>Listens for verbal commands in the Ruby language!</b></li>
238 #            <li><b>Ignores Perl, Java, and all C variants.</b></li>
239 #            <li><b>Karate-Chop Action!!!</b></li>
240 #            <li><b>Matz signature on left leg.</b></li>
241 #            <li><b>Gem studded eyes... Rubies, of course!</b></li>
242 #        </ul>
244 #        <p>
245 #             Call for a price, today!
246 #        </p>
248 #      </body>
249 #    </html>
252 # == Notes
254 # There are a variety of templating solutions available in various Ruby projects.
255 # For example, RDoc, distributed with Ruby, uses its own template engine, which
256 # can be reused elsewhere.
258 # Other popular engines could be found in the corresponding
259 # {Category}[https://www.ruby-toolbox.com/categories/template_engines] of
260 # The Ruby Toolbox.
262 class ERB
263   Revision = '$Date::                           $' # :nodoc: #'
264   deprecate_constant :Revision
266   # Returns revision information for the erb.rb module.
267   def self.version
268     VERSION
269   end
271   #
272   # Constructs a new ERB object with the template specified in _str_.
273   #
274   # An ERB object works by building a chunk of Ruby code that will output
275   # the completed template when run.
276   #
277   # If _trim_mode_ is passed a String containing one or more of the following
278   # modifiers, ERB will adjust its code generation as listed:
279   #
280   #     %  enables Ruby code processing for lines beginning with %
281   #     <> omit newline for lines starting with <% and ending in %>
282   #     >  omit newline for lines ending in %>
283   #     -  omit blank lines ending in -%>
284   #
285   # _eoutvar_ can be used to set the name of the variable ERB will build up
286   # its output in.  This is useful when you need to run multiple ERB
287   # templates through the same binding and/or when you want to control where
288   # output ends up.  Pass the name of the variable to be used inside a String.
289   #
290   # === Example
291   #
292   #  require "erb"
293   #
294   #  # build data class
295   #  class Listings
296   #    PRODUCT = { :name => "Chicken Fried Steak",
297   #                :desc => "A well messages pattie, breaded and fried.",
298   #                :cost => 9.95 }
299   #
300   #    attr_reader :product, :price
301   #
302   #    def initialize( product = "", price = "" )
303   #      @product = product
304   #      @price = price
305   #    end
306   #
307   #    def build
308   #      b = binding
309   #      # create and run templates, filling member data variables
310   #      ERB.new(<<~'END_PRODUCT', trim_mode: "", eoutvar: "@product").result b
311   #        <%= PRODUCT[:name] %>
312   #        <%= PRODUCT[:desc] %>
313   #      END_PRODUCT
314   #      ERB.new(<<~'END_PRICE', trim_mode: "", eoutvar: "@price").result b
315   #        <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
316   #        <%= PRODUCT[:desc] %>
317   #      END_PRICE
318   #    end
319   #  end
320   #
321   #  # setup template data
322   #  listings = Listings.new
323   #  listings.build
324   #
325   #  puts listings.product + "\n" + listings.price
326   #
327   # _Generates_
328   #
329   #  Chicken Fried Steak
330   #  A well messages pattie, breaded and fried.
331   #
332   #  Chicken Fried Steak -- 9.95
333   #  A well messages pattie, breaded and fried.
334   #
335   def initialize(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eoutvar=NOT_GIVEN, trim_mode: nil, eoutvar: '_erbout')
336     # Complex initializer for $SAFE deprecation at [Feature #14256]. Use keyword arguments to pass trim_mode or eoutvar.
337     if safe_level != NOT_GIVEN
338       warn 'Passing safe_level with the 2nd argument of ERB.new is deprecated. Do not use it, and specify other arguments as keyword arguments.', uplevel: 1
339     end
340     if legacy_trim_mode != NOT_GIVEN
341       warn 'Passing trim_mode with the 3rd argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, trim_mode: ...) instead.', uplevel: 1
342       trim_mode = legacy_trim_mode
343     end
344     if legacy_eoutvar != NOT_GIVEN
345       warn 'Passing eoutvar with the 4th argument of ERB.new is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...) instead.', uplevel: 1
346       eoutvar = legacy_eoutvar
347     end
349     compiler = make_compiler(trim_mode)
350     set_eoutvar(compiler, eoutvar)
351     @src, @encoding, @frozen_string = *compiler.compile(str)
352     @filename = nil
353     @lineno = 0
354     @_init = self.class.singleton_class
355   end
356   NOT_GIVEN = Object.new
357   private_constant :NOT_GIVEN
359   ##
360   # Creates a new compiler for ERB.  See ERB::Compiler.new for details
362   def make_compiler(trim_mode)
363     ERB::Compiler.new(trim_mode)
364   end
366   # The Ruby code generated by ERB
367   attr_reader :src
369   # The encoding to eval
370   attr_reader :encoding
372   # The optional _filename_ argument passed to Kernel#eval when the ERB code
373   # is run
374   attr_accessor :filename
376   # The optional _lineno_ argument passed to Kernel#eval when the ERB code
377   # is run
378   attr_accessor :lineno
380   #
381   # Sets optional filename and line number that will be used in ERB code
382   # evaluation and error reporting. See also #filename= and #lineno=
383   #
384   #   erb = ERB.new('<%= some_x %>')
385   #   erb.render
386   #   # undefined local variable or method `some_x'
387   #   #   from (erb):1
388   #
389   #   erb.location = ['file.erb', 3]
390   #   # All subsequent error reporting would use new location
391   #   erb.render
392   #   # undefined local variable or method `some_x'
393   #   #   from file.erb:4
394   #
395   def location=((filename, lineno))
396     @filename = filename
397     @lineno = lineno if lineno
398   end
400   #
401   # Can be used to set _eoutvar_ as described in ERB::new.  It's probably
402   # easier to just use the constructor though, since calling this method
403   # requires the setup of an ERB _compiler_ object.
404   #
405   def set_eoutvar(compiler, eoutvar = '_erbout')
406     compiler.put_cmd = "#{eoutvar}.<<"
407     compiler.insert_cmd = "#{eoutvar}.<<"
408     compiler.pre_cmd = ["#{eoutvar} = +''"]
409     compiler.post_cmd = [eoutvar]
410   end
412   # Generate results and print them. (see ERB#result)
413   def run(b=new_toplevel)
414     print self.result(b)
415   end
417   #
418   # Executes the generated ERB code to produce a completed template, returning
419   # the results of that code.  (See ERB::new for details on how this process
420   # can be affected by _safe_level_.)
421   #
422   # _b_ accepts a Binding object which is used to set the context of
423   # code evaluation.
424   #
425   def result(b=new_toplevel)
426     unless @_init.equal?(self.class.singleton_class)
427       raise ArgumentError, "not initialized"
428     end
429     eval(@src, b, (@filename || '(erb)'), @lineno)
430   end
432   # Render a template on a new toplevel binding with local variables specified
433   # by a Hash object.
434   def result_with_hash(hash)
435     b = new_toplevel(hash.keys)
436     hash.each_pair do |key, value|
437       b.local_variable_set(key, value)
438     end
439     result(b)
440   end
442   ##
443   # Returns a new binding each time *near* TOPLEVEL_BINDING for runs that do
444   # not specify a binding.
446   def new_toplevel(vars = nil)
447     b = TOPLEVEL_BINDING
448     if vars
449       vars = vars.select {|v| b.local_variable_defined?(v)}
450       unless vars.empty?
451         return b.eval("tap {|;#{vars.join(',')}| break binding}")
452       end
453     end
454     b.dup
455   end
456   private :new_toplevel
458   # Define _methodname_ as instance method of _mod_ from compiled Ruby source.
459   #
460   # example:
461   #   filename = 'example.rhtml'   # 'arg1' and 'arg2' are used in example.rhtml
462   #   erb = ERB.new(File.read(filename))
463   #   erb.def_method(MyClass, 'render(arg1, arg2)', filename)
464   #   print MyClass.new.render('foo', 123)
465   def def_method(mod, methodname, fname='(ERB)')
466     src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n"
467     mod.module_eval do
468       eval(src, binding, fname, -1)
469     end
470   end
472   # Create unnamed module, define _methodname_ as instance method of it, and return it.
473   #
474   # example:
475   #   filename = 'example.rhtml'   # 'arg1' and 'arg2' are used in example.rhtml
476   #   erb = ERB.new(File.read(filename))
477   #   erb.filename = filename
478   #   MyModule = erb.def_module('render(arg1, arg2)')
479   #   class MyClass
480   #     include MyModule
481   #   end
482   def def_module(methodname='erb')
483     mod = Module.new
484     def_method(mod, methodname, @filename || '(ERB)')
485     mod
486   end
488   # Define unnamed class which has _methodname_ as instance method, and return it.
489   #
490   # example:
491   #   class MyClass_
492   #     def initialize(arg1, arg2)
493   #       @arg1 = arg1;  @arg2 = arg2
494   #     end
495   #   end
496   #   filename = 'example.rhtml'  # @arg1 and @arg2 are used in example.rhtml
497   #   erb = ERB.new(File.read(filename))
498   #   erb.filename = filename
499   #   MyClass = erb.def_class(MyClass_, 'render()')
500   #   print MyClass.new('foo', 123).render()
501   def def_class(superklass=Object, methodname='result')
502     cls = Class.new(superklass)
503     def_method(cls, methodname, @filename || '(ERB)')
504     cls
505   end