├── VERSION
├── .gitignore
├── views
├── testview3.nlt
├── testview.nlt
├── layout.nlt
├── layout3.nlt
├── testview4.nlt
├── layout2.nlt
├── testview6.nlt
├── testview2.nlt
├── testview7.nlt
├── example.nlt
├── bigtemplate.nlt
└── testview5.nlt
├── Makefile
├── example.rb
├── pkg
├── gemspec_template.rb
└── build_gemspec.rb
├── bench.rb
├── nolate.gemspec
├── LICENSE
├── test.rb
├── README
└── lib
└── nolate.rb
/VERSION:
--------------------------------------------------------------------------------
1 | 0.0.2
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | pkg/*.gem
2 |
--------------------------------------------------------------------------------
/views/testview3.nlt:
--------------------------------------------------------------------------------
1 | <%= @x %>
2 |
--------------------------------------------------------------------------------
/views/testview.nlt:
--------------------------------------------------------------------------------
1 | test <%= 2+2 %> view
2 |
--------------------------------------------------------------------------------
/views/layout.nlt:
--------------------------------------------------------------------------------
1 | Header
2 | <%#content%>
3 | Footer
4 |
--------------------------------------------------------------------------------
/views/layout3.nlt:
--------------------------------------------------------------------------------
1 | Other Header
2 | <%#content%>
3 | Other Footer
4 |
--------------------------------------------------------------------------------
/views/testview4.nlt:
--------------------------------------------------------------------------------
1 | <% (1..4).each{|x| %>
2 | Number <%= x %>
3 | <% } %>
4 |
--------------------------------------------------------------------------------
/views/layout2.nlt:
--------------------------------------------------------------------------------
1 | Header
2 | <%#content%>
3 | <%=
4 | nolate("nested call")
5 | %>
6 | Footer
7 |
--------------------------------------------------------------------------------
/views/testview6.nlt:
--------------------------------------------------------------------------------
1 | <% y = [1,2,3].map {|x| %>
2 | <%= x*x %>
3 | <% } %>
4 | <%= y.inspect %>
5 |
--------------------------------------------------------------------------------
/views/testview2.nlt:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%=
4 | # 2+2 = 4
5 | 2+2
6 | %>
7 |
8 |
9 |
--------------------------------------------------------------------------------
/views/testview7.nlt:
--------------------------------------------------------------------------------
1 | zap
2 | <% #comment one
3 | x = 2+2
4 | #comment two %>
5 | <%= x %>
6 | ciao
7 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | test:
2 | ruby test.rb
3 |
4 | gem:
5 | ruby pkg/build_gemspec.rb
6 | gem build nolate.gemspec
7 | mv -f *.gem pkg
8 |
--------------------------------------------------------------------------------
/example.rb:
--------------------------------------------------------------------------------
1 | load 'lib/nolate.rb'
2 |
3 | hash = {:title => "Hello World!"}
4 | @ivar = "Instance Variable Content"
5 | puts nlt(:example,hash) # Check views/example.nlt for more info
6 |
--------------------------------------------------------------------------------
/views/example.nlt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Test <%#title%>
5 |
6 |
7 |
8 | List of items
9 | <% (0..5).each{|x| %>
10 |
<%=x%>
11 | <% } %>
12 |
13 |
14 | You can access the substitutions hash from Ruby code inside the template
15 | using the __sub variable name:
16 |
17 | :title is set to -> <%= __sub[:title].inspect %>
18 |
19 |
20 |
21 | Another way to pass values to the template is via instance variables that
22 | are accessible without any special convention:
23 |
24 | @ivar is set to <%= @ivar.inspect %>
25 |
26 |
27 |
28 | Example of conditional:
29 | <% if false %>
30 | Ruby is lame
31 | <% else %>
32 | Ruby is a cool programming language
33 | <% end %>
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/pkg/gemspec_template.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | Gem::Specification.new do |s|
4 | s.specification_version = 2 if s.respond_to? :specification_version=
5 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6 |
7 | s.name = %q{nolate}
8 | s.version = %version%
9 | s.summary = %q{Ruby Template System}
10 | s.description = %q{Pure Ruby template engine optimized for speed}
11 | s.authors = ["Salvatore Sanfilippo","Michel Martens","Bruno Michel","Emmanuel Oga"]
12 | s.date = %q{2011-04-05}
13 | s.email = %q{antirez@gmail.com}
14 | s.extra_rdoc_files = ["LICENSE"]
15 | s.homepage = %q{http://github.com/antirez/nolaote}
16 | s.require_paths = ["lib"]
17 | s.rubygems_version = %q{1.5.0}
18 |
19 | s.files = %files%
20 | end
21 |
--------------------------------------------------------------------------------
/views/bigtemplate.nlt:
--------------------------------------------------------------------------------
1 |
2 |
3 | Long template with all the features Yeah!. 2 + 2 is: <%= # 2+2 = 4
4 | 2+2
5 | %>
6 |
7 | <%= @x %>
8 |
9 | <% @x %>
10 |
11 | <%#periquin%>
12 |
13 | <% (1..2).each{|x| %>
14 | Number <%= x %>
15 | <% } %>
16 |
17 |
18 |
19 |
20 | Long template with all the features Yeah!. 2 + 2 is: <%= # 2+2 = 4
21 | 2+2
22 | %>
23 |
24 | <%= @x %>
25 |
26 | <% @x %>
27 |
28 | <%#periquin%>
29 |
30 | <% (1..2).each{|x| %>
31 | Number <%= x %>
32 | <% } %>
33 |
34 |
35 |
36 |
37 | Long template with all the features Yeah!. 2 + 2 is: <%= # 2+2 = 4
38 | 2+2
39 | %>
40 |
41 | <%= @x %>
42 |
43 | <% @x %>
44 |
45 | <%#periquin%>
46 |
47 | <% (1..2).each{|x| %>
48 | Number <%= x %>
49 | <% } %>
50 |
51 |
52 |
--------------------------------------------------------------------------------
/views/testview5.nlt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Test <%#title%>
5 |
6 |
7 |
8 | List of items
9 | <% (0..5).each{|x| %>
10 |
<%=x%>
11 | <% } %>
12 |
13 |
14 | You can access the substitutions hash from Ruby code inside the template
15 | using the __sub variable name:
16 |
17 | :title is set to -> <%= __sub[:title].inspect %>
18 |
19 |
20 | <%
21 | # Example
22 | # Error
23 | 4+4
24 | %>
25 |
26 |
27 | Another way to pass values to the template is via instance variables that
28 | are accessible without any special convention:
29 |
30 | @ivar is set to <%= @ivar.inspect %>
31 |
32 |
33 |
34 | Example of conditional:
35 | <% if false %>
36 | Ruby is lame
37 | <% else %>
38 | Ruby is a cool programming language
39 | <% end %>
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/pkg/build_gemspec.rb:
--------------------------------------------------------------------------------
1 | class GemIt
2 | def initialize
3 | @template = File.read("pkg/gemspec_template.rb")
4 | end
5 | def list_files(path,parent=nil)
6 | files = []
7 | dir = Dir.open(path)
8 | dir.to_a.each{|f|
9 | next if f[0..0] == "."
10 | if File.directory? f
11 | files += list_files("#{path}/#{f}","#{f}")
12 | else
13 | files << (parent ? "#{parent}/#{f}" : f)
14 | end
15 | }
16 | files
17 | end
18 | def gemspec
19 | files = GemIt.new.list_files(".").sort
20 | version = File.read("VERSION").chomp
21 | gemspec = @template
22 | gemspec.sub!("%version%",version.inspect)
23 | gemspec.sub!("%files%",files.inspect)
24 | end
25 | end
26 |
27 | gemspec = GemIt.new.gemspec
28 | f = File.open("nolate.gemspec","w").write(gemspec)
29 |
--------------------------------------------------------------------------------
/bench.rb:
--------------------------------------------------------------------------------
1 | load "lib/nolate.rb"
2 |
3 | def bench(descr, times)
4 | start = Time.now.to_f
5 | times.times { yield }
6 | elapsed = Time.now.to_f - start
7 | reqsec = times / elapsed
8 | puts "#{descr.ljust(25)}: #{(reqsec).to_i.to_s.rjust(10)} requests/second"
9 | $template = ""
10 | end
11 |
12 | TEMPLATE = <<-TEMPLATE * 3
13 |
14 |
15 | Long template with all the features Yeah!. 2 + 2 is: <%= # 2+2 = 4
16 | 2+2
17 | %>
18 |
19 | <%= @x %>
20 |
21 | <% @x %>
22 |
23 | <%#periquin%>
24 |
25 | <% (1..2).each{|x| %>
26 | Number <%= x %>
27 | <% } %>
28 |
29 |
30 | TEMPLATE
31 |
32 | TIMES = 30_000
33 |
34 | bench("empty template" , TIMES) { nolate("") }
35 | bench("small constant template" , TIMES) { nolate("nosub") }
36 | bench("simple substitution" , TIMES) { nolate("simple <%= 'sub' %>") }
37 | bench("hash substitution" , TIMES) { nolate("hash sub <%#x%>") }
38 | bench("testview2 file template" , TIMES) { nlt(:testview2) }
39 | bench("big template .nlt", TIMES/5) { @x = 1; nlt(:bigtemplate, :x => 1) }
40 | bench("big template inline", TIMES/10) { @x = 1; nolate(TEMPLATE, :x => 1) }
41 |
--------------------------------------------------------------------------------
/nolate.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | Gem::Specification.new do |s|
4 | s.specification_version = 2 if s.respond_to? :specification_version=
5 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6 |
7 | s.name = %q{nolate}
8 | s.version = "0.0.2"
9 | s.summary = %q{Ruby Template System}
10 | s.description = %q{Pure Ruby template engine optimized for speed}
11 | s.authors = ["Salvatore Sanfilippo","Michel Martens","Bruno Michel","Emmanuel Oga"]
12 | s.date = %q{2011-04-05}
13 | s.email = %q{antirez@gmail.com}
14 | s.extra_rdoc_files = ["LICENSE"]
15 | s.homepage = %q{http://github.com/antirez/nolaote}
16 | s.require_paths = ["lib"]
17 | s.rubygems_version = %q{1.5.0}
18 |
19 | s.files = ["LICENSE", "Makefile", "README", "VERSION", "bench.rb", "example.rb", "lib/nolate.rb", "nolate.gemspec", "pkg/build_gemspec.rb", "pkg/gemspec_template.rb", "pkg/nolate-0.0.2.gem", "test.rb", "views/bigtemplate.nlt", "views/example.nlt", "views/layout.nlt", "views/layout2.nlt", "views/layout3.nlt", "views/testview.nlt", "views/testview2.nlt", "views/testview3.nlt", "views/testview4.nlt", "views/testview5.nlt", "views/testview6.nlt", "views/testview7.nlt"]
20 | end
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Salvatore Sanfilippo
2 |
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are
7 | met:
8 |
9 | * Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/test.rb:
--------------------------------------------------------------------------------
1 | require 'test/unit'
2 | load 'lib/nolate.rb'
3 |
4 | class MyExampleClass
5 | def method_one
6 | @x = "Hello"
7 | nolate("<%= @x %>")
8 | end
9 |
10 | def method_two
11 | @x = "World"
12 | nlt(:testview3)
13 | end
14 | end
15 |
16 | class NolateTest < Test::Unit::TestCase
17 | def test_basic
18 | assert_equal("",nolate(""))
19 | assert_equal("nosub",nolate("nosub"))
20 | assert_equal("simple sub",nolate("simple <%= 'sub' %>"))
21 | assert_equal("hash sub 1",nolate("hash sub <%#x%>",{:x => 1}))
22 | assert_equal("just eval",nolate("just ev<% 'sub' %>al"))
23 | assert_equal("test 4 view\n",nlt(:testview))
24 | assert_equal("test 4 view\n",nlt("testview.nlt"))
25 | assert_equal("\n\n4\n\n\n",nlt(:testview2))
26 | assert_equal("3",nolate("<%x=2%><%=x+1%>"))
27 | assert_equal("Hello",MyExampleClass.new.method_one)
28 | assert_equal("World\n",MyExampleClass.new.method_two)
29 | assert_equal("\n1\n\n4\n\n9\n\n[1, 4, 9]\n",nlt(:testview6))
30 | assert_equal("zap\n\n4\nciao\n",nlt(:testview7))
31 | end
32 |
33 | def test_iter
34 | assert_equal(<<-OUTPUT, nlt(:testview4))
35 | Number 1
36 | Number 2
37 | Number 3
38 | Number 4
39 |
40 | OUTPUT
41 | end
42 |
43 | def test_layout
44 | nlt_set_layout(:layout)
45 | assert_equal("Header\n2+2=4\nFooter\n",nolate("2+2=<%= 2+2 %>"))
46 | nlt_set_layout(:layout2)
47 | assert_equal("Header\nciao\nnested call\nFooter\n",nolate("ciao"))
48 | nlt_set_layout(:layout)
49 | assert_equal("2+2=4",nolate("2+2=<%= 2+2 %>",{},{:layout => false}))
50 | assert_equal("Other Header\n2+2=4\nOther Footer\n",
51 | nolate("2+2=<%= 2+2 %>",{},{:layout => :layout3}))
52 | end
53 |
54 | def test_error_lines
55 | # Make sure that compiled template and template have the code in the
56 | # same lines, so that eval() will report good error traces.
57 | text = File.read("views/testview5.nlt").to_a
58 | compiled = nlt_compile(File.read("views/testview5.nlt")).split("\n")
59 | assert(text[3] =~ /title/ && compiled[3] =~ /title/)
60 | assert(text[8] =~ /each/ && compiled[8] =~ /each/)
61 | assert(text[22] =~ /4\+4/ && compiled[22] =~ /4\+4/)
62 | assert(text[29] =~ /ivar/ && compiled[29] =~ /ivar/)
63 | assert(text[36] =~ /else/ && compiled[36] =~ /else/)
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Nolate - NO LAme TEmplate system
2 |
3 | OVERVIEW
4 | --------
5 |
6 | Nolate is a template system similar to erb that is designed for not consuming
7 | some huge amount of CPU without a good reason. It is written in pure Ruby.
8 | Nolate is distributed under a two clause BSD license for max freedom.
9 |
10 | Templates can include code inside <%= %> that is evaluated with eval() and
11 | substituted to the string.
12 |
13 | Also occurrences of <%#something%> are substituted with the value of the
14 | hash field :something of an additional hash passed to nolate() or nlt()
15 | functions.
16 |
17 | IS IT SUPER FAST?
18 | -----------------
19 |
20 | Fast enough that a small template substitution is not measurable by the
21 | apache benchmark against a sample Sinatra application.
22 | Surprisingly this is not as common as it should be.
23 |
24 | HOW TO USE IT?
25 | --------------
26 |
27 | Nolate consists of just a few functions. The first is nolate() that is the core
28 | of the template system:
29 |
30 | nolate("The sum is <%= 2+2 %> Also substitute <%#myfield%> ok",
31 | {:myfield => 10})
32 |
33 | The array is optional, if you don't have <%#%> style substitutions you can
34 | simply omit it.
35 |
36 | The second function is nlt(), and is used to also handle loading the template
37 | from a 'views' directory. The above example can be translated using nlt()
38 | just creating a file 'views/index.nlt' with the following content:
39 |
40 | The sum is <%= 2+2 %> Also substitute <%#myfield%> ok
41 |
42 | Then we can use nlt() calling:
43 |
44 | nlt("index.nlt", {:myfield => "something"})
45 |
46 | the nlt() funciton will take care to cache templates into memory.
47 | In order to flush this templates to force reloading just call the third and
48 | final provided function:
49 |
50 | nlt_flush_templates()
51 |
52 | It is possible to pass the template name as a symbol like in:
53 |
54 | nlt(:index)
55 |
56 | nlt will add ".nlt" at the end of the name when it is a symbol.
57 |
58 | SUPPORTED SUBSTITUTIONS
59 | -----------------------
60 |
61 | <%= somecode %> Evaluates somecode and substitutes the return value.
62 | <% somecode %> Evaluates somecode.
63 | <%#filed_name%> Substituted the value of the specified filed of the hash
64 | passed to nolate() or nlt() as optional argument.
65 |
66 | It is possible to interleave template and Ruby code together like in the
67 | following example:
68 |
69 | <% (0..5).each{|x| %>
70 | <%=x%>
71 | <% } %>
72 |
73 | USING LAYOUTS
74 | -------------
75 |
76 | Nolate suppots the concept of layout. You can specify to use a layout using
77 | the following call:
78 |
79 | nlt_set_layout(:layout)
80 |
81 | The above call specifies to use "views/layout.nlt" as template.
82 |
83 | The layout is a normal nolate template that contains somewhere a
84 | substitution in the form of: <%#content%>. When a layout is set what happens
85 | is that all the calls to nolate() or nlt() are processed, then the result
86 | is substituted to the layout template.
87 |
88 | The layout template can also include any other standard nolate substitution
89 | and code evaluation.
90 |
91 | It is possible to change layout at runtime, or to disable the layout setting
92 | it to nil.
93 |
94 | CONTRIBUTE
95 | ----------
96 |
97 | Please send me pull requests: http://github.com/antirez/nolate
98 |
99 | So far thank you to:
100 |
101 | @soveran
102 | @brmichel
103 | @JEG2
104 | Emmanuel Oga (https://github.com/EmmanuelOga)
105 | @czarneckid
106 |
107 | It is not too late...
108 | Salvatore
109 |
--------------------------------------------------------------------------------
/lib/nolate.rb:
--------------------------------------------------------------------------------
1 | # NOLATE, A NO LAme TEmplate system
2 | #
3 | # Please read the README file for more information
4 | #
5 | # Copyright (c) 2011, Salvatore Sanfilippo
6 | #
7 | # All rights reserved.
8 | #
9 | # Redistribution and use in source and binary forms, with or without
10 | # modification, are permitted provided that the following conditions are
11 | # met:
12 | #
13 | # * Redistributions of source code must retain the above copyright
14 | # notice, this list of conditions and the following disclaimer.
15 | #
16 | # * Redistributions in binary form must reproduce the above copyright
17 | # notice, this list of conditions and the following disclaimer in the
18 | # documentation and/or other materials provided with the distribution.
19 | #
20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | #
32 |
33 | def nlt_empty_binding(__sub_)
34 | __sub = __sub_
35 | return binding()
36 | end
37 |
38 | def nlt_templates
39 | $nolate_templates ||= {}
40 | end
41 |
42 | def nlt_flush_templates
43 | $nolate_templates = {}
44 | end
45 |
46 | def nlt_set_layout(layout)
47 | $nolate_layout = layout
48 | end
49 |
50 | def nlt_parse(str)
51 | i = -1 # I wish I had map.with_index in 1.8 :(
52 | prev_was_eval = false # Previous token was an :eval?
53 | str.split(/<%(.*?)%>/m).map do |s|
54 | i, first_char = i + 1, s[0..0]
55 | newlines = s.count("\n")
56 | if i % 2 == 0
57 | j = 0
58 | if prev_was_eval and s != "\n" and s != "\r\n"
59 | j += 1 if s[j..j] == "\r"
60 | j += 1 if s[j..j] == "\n"
61 | end
62 | prev_was_eval = false
63 | [:verb, s[j..-1].inspect, newlines]
64 | elsif first_char == "="
65 | prev_was_eval = false
66 | [:evalo, s[1..-1], newlines]
67 | elsif first_char == "#"
68 | prev_was_eval = false
69 | [:sub, s[1..-1].to_sym, newlines]
70 | else
71 | prev_was_eval = true
72 | [:eval, s, 0]
73 | end
74 | end
75 | end
76 |
77 | def nlt_compile(template)
78 | s = "__=[]; "
79 | nlt_parse(template).each do |action, param, newlines|
80 | if action == :evalo or action == :eval
81 | if param[(-1..-1)] != "\n" and param.index("#")
82 | lines = param.split("\n")
83 | if lines[-1] =~ /^ *#/
84 | lines[-1] = ""
85 | param = lines.join("\n")
86 | end
87 | end
88 | end
89 | case action
90 | when :evalo then s << "@__ = (#{param}); __<< @__.to_s; @__; "
91 | when :eval then s << "#{param}; "
92 | when :sub then s << "__<< __sub[#{param.to_sym.inspect}]; @__; "
93 | when :verb then s << "__<<#{param}; @__; "
94 | end
95 | s << "\n"*newlines
96 | end
97 | s << "\n__.join"
98 | end
99 |
100 | def nlt_eval(code, sub = {}, opt = {}, file="evaluated_string")
101 | # Make sure that nested calls will not substitute the layout
102 | saved = @nolate_no_layout
103 | @nolate_no_layout = true
104 | content = eval(code, nlt_empty_binding(sub), file, 1)
105 | @nolate_no_layout = saved
106 |
107 | # And... make sure that the layout will not trigger an infinite recursion
108 | # substituting itself forever.
109 | if $nolate_layout and !@nolate_no_layout and !(opt[:layout] == false)
110 | saved = $nolate_layout
111 | if !opt[:layout]
112 | use = $nolate_layout
113 | else
114 | use = opt[:layout]
115 | end
116 | $nolate_layout = nil
117 | content = nlt(use,{:content => content})
118 | $nolate_layout = saved
119 | end
120 | content
121 | end
122 |
123 | def nlt(viewname, sub={}, opt={})
124 | viewname = "#{viewname}.nlt" if viewname.is_a?(Symbol)
125 | unless nlt_templates[viewname]
126 | filename = "views/#{viewname}"
127 | raise "NOLATE error: no template at #{filename}" \
128 | unless File.exists?(filename)
129 | nlt_templates[viewname] = nlt_compile(File.read(filename))
130 | end
131 | nlt_eval(nlt_templates[viewname], sub, opt, "views/#{viewname}")
132 | end
133 |
134 | def nolate(str, sub={}, opt={})
135 | nlt_eval(nlt_compile(str), sub, opt)
136 | end
137 |
--------------------------------------------------------------------------------