Class: Tenjin::Engine
- Inherits:
-
Object
- Object
- Tenjin::Engine
- Defined in:
- lib/tenjin.rb
Overview
engine class for templates
Engine class supports the followings.
-
template caching
-
partial template
-
layout template
-
capturing (experimental)
ex. file ‘ex_list.rbhtml’
<ul>
<?rb for item in @items ?>
<li>#{item}</li>
<?rb end ?>
</ul>
ex. file ‘ex_layout.rbhtml’
<html>
<body>
<h1>${@title}</li>
#{@_content}
<?rb import 'footer.rbhtml' ?>
</body>
</html>
ex. file ‘main.rb’
require 'tenjin'
= {:prefix=>'ex_', :postfix=>'.rbhtml', :layout=>'ex_layout.rbhtml'}
engine = Tenjin::Engine.new()
context = {:title=>'Tenjin Example', :items=>['foo', 'bar', 'baz']}
output = engine.render(:list, context) # or 'ex_list.rbhtml'
print output
Instance Method Summary collapse
- #cachename(filename) ⇒ Object
-
#create_template(filename, _context = nil) ⇒ Object
create template object from file.
-
#find_template_file(template_name) ⇒ Object
find template filename.
-
#get_template(template_name, _context = nil) ⇒ Object
get template object.
- #hook_context(context) ⇒ Object
-
#initialize(options = {}) ⇒ Engine
constructor
initializer of Engine class.
-
#load_cachefile(cache_filename, template) ⇒ Object
load template from cache file.
-
#read_template_file(filename, _context) ⇒ Object
read template file and preprocess it.
-
#register_template(template_name, template) ⇒ Object
register template object.
-
#render(template_name, context = Context.new, layout = true) ⇒ Object
get template object and evaluate it with context object.
-
#store_cachefile(cache_filename, template) ⇒ Object
store template into cache file.
-
#to_filename(template_name) ⇒ Object
convert short name into filename (ex. ‘:list’ => ‘template/list.rb.html’).
Constructor Details
#initialize(options = {}) ⇒ Engine
initializer of Engine class.
options:
- :prefix
-
prefix string for template name (ex. ‘template/’)
- :postfix
-
postfix string for template name (ex. ‘.rbhtml’)
- :layout
-
layout template name (default nil)
- :path
-
array of directory name (default nil)
- :cache
-
save converted ruby code into file or not (default true)
- :path
-
list of directory (default nil)
- :preprocess
-
flag to activate preprocessing (default nil)
- :templateclass
-
template class object (default Tenjin::Template)
812 813 814 815 816 817 818 819 820 821 822 |
# File 'lib/tenjin.rb', line 812 def initialize(={}) @prefix = [:prefix] || '' @postfix = [:postfix] || '' @layout = [:layout] @cache = .fetch(:cache, true) @path = [:path] @preprocess = .fetch(:preprocess, nil) @templateclass = .fetch(:templateclass, Template) @init_opts_for_template = @templates = {} # filename->template end |
Instance Method Details
#cachename(filename) ⇒ Object
861 862 863 |
# File 'lib/tenjin.rb', line 861 def cachename(filename) return (filename + '.cache').untaint end |
#create_template(filename, _context = nil) ⇒ Object
create template object from file
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 |
# File 'lib/tenjin.rb', line 866 def create_template(filename, _context=nil) template = @templateclass.new(nil, @init_opts_for_template) template. = Time.now() cache_filename = cachename(filename) _context = hook_context(Context.new) if _context.nil? if !@cache input = read_template_file(filename, _context) template.convert(input, filename) elsif !test(?f, cache_filename) || File.mtime(cache_filename) < File.mtime(filename) #$stderr.puts "*** debug: load original" input = read_template_file(filename, _context) template.convert(input, filename) store_cachefile(cache_filename, template) else #$stderr.puts "*** debug: load cache" template.filename = filename load_cachefile(cache_filename, template) end return template end |
#find_template_file(template_name) ⇒ Object
find template filename
831 832 833 834 835 836 837 838 839 840 841 842 |
# File 'lib/tenjin.rb', line 831 def find_template_file(template_name) filename = to_filename(template_name) if @path for dir in @path filepath = "#{dir}#{File::SEPARATOR}#{filename}" return filepath if test(?f, filepath.untaint) end else return filename if test(?f, filename.dup.untaint) # dup is required for frozen string end raise Errno::ENOENT.new("#{filename} (path=#{@path.inspect})") end |
#get_template(template_name, _context = nil) ⇒ Object
get template object
908 909 910 911 912 913 914 915 916 917 |
# File 'lib/tenjin.rb', line 908 def get_template(template_name, _context=nil) template = @templates[template_name] t = template unless t && t. && t.filename && t. >= File.mtime(t.filename) filename = find_template_file(template_name) template = create_template(filename, _context) # _context is passed only for preprocessor register_template(template_name, template) end return template end |
#hook_context(context) ⇒ Object
945 946 947 948 949 950 951 952 953 954 |
# File 'lib/tenjin.rb', line 945 def hook_context(context) if !context context = Context.new elsif context.is_a?(Hash) context = Context.new(context) end context._engine = self context._layout = nil return context end |
#load_cachefile(cache_filename, template) ⇒ Object
load template from cache file
899 900 901 902 903 904 905 |
# File 'lib/tenjin.rb', line 899 def load_cachefile(cache_filename, template) s = File.read(cache_filename) if s.sub!(/\A\#\@ARGS (.*?)\r?\n/, '') template.args = $1.split(',') end template.script = s end |
#read_template_file(filename, _context) ⇒ Object
read template file and preprocess it
845 846 847 848 849 850 851 852 853 |
# File 'lib/tenjin.rb', line 845 def read_template_file(filename, _context) return File.read(filename) if !@preprocess _context ||= {} if _context.is_a?(Hash) || _context._engine.nil? _context = hook_context(_context) end preprocessor = Preprocessor.new(filename) return preprocessor.render(_context) end |
#register_template(template_name, template) ⇒ Object
register template object
856 857 858 859 |
# File 'lib/tenjin.rb', line 856 def register_template(template_name, template) #template.timestamp = Time.new unless template.timestamp @templates[template_name] = template end |
#render(template_name, context = Context.new, layout = true) ⇒ Object
get template object and evaluate it with context object. if argument ‘layout’ is true then default layout file (specified at initializer) is used as layout template, else if false then no layout template is used. if argument ‘layout’ is string, it is regarded as layout template name.
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 |
# File 'lib/tenjin.rb', line 924 def render(template_name, context=Context.new, layout=true) #context = Context.new(context) if context.is_a?(Hash) context = hook_context(context) while true template = get_template(template_name, context) # context is passed only for preprocessor _buf = context._buf output = template.render(context) context._buf = _buf unless context['_layout'].nil? layout = context['_layout'] context['_layout'] = nil end layout = @layout if layout == true or layout.nil? break unless layout template_name = layout layout = false context['_content'] = output end return output end |
#store_cachefile(cache_filename, template) ⇒ Object
store template into cache file
888 889 890 891 892 893 894 895 896 |
# File 'lib/tenjin.rb', line 888 def store_cachefile(cache_filename, template) s = template.script s = "\#@ARGS #{template.args.join(',')}\n#{s}" if template.args File.open(cache_filename, 'w') do |f| f.flock(File::LOCK_EX) f.write(s) #f.lock(FIle::LOCK_UN) # File#close() unlocks automatically end end |
#to_filename(template_name) ⇒ Object
convert short name into filename (ex. ‘:list’ => ‘template/list.rb.html’)
825 826 827 828 |
# File 'lib/tenjin.rb', line 825 def to_filename(template_name) name = template_name return name.is_a?(Symbol) ? "#{@prefix}#{name}#{@postfix}" : name end |