Amrita2 compiles HTML template to Ruby module.
This is the compiled Ruby code from sample/hello.rb and will be evaluated in a Module.
extend Amrita2::Runtime def self.expand_template(out,&block) new_context(out) do block.call(MainContext) if block_given? get_mainstream << "<html>\n <body>\n " output_substream(:title) get_mainstream << "\n " output_substream(:body) get_mainstream << "\n </body>\n</html>\n\n" end end module MainContext extend Amrita2::Runtime def title(val=nil,attrs={},&block) attrs = val if val.kind_of?(Hash) new_context(get_substream(:title)) do if val == true get_mainstream << "<h1 id='title'>title will be inserted here</h1>" else if attrs.size == 0 get_mainstream << "<h1>" get_mainstream << val.amrita_sanitize get_mainstream << "</h1>" else a = { } attrs.each do |k,v| a[k] = v end e = new_element("h1", a) e.delete_attribute("id") get_mainstream << start_tag(e) get_mainstream << val.amrita_sanitize get_mainstream << end_tag(e) end end end end module_function :title def body(val=nil,attrs={},&block) attrs = val if val.kind_of?(Hash) new_context(get_substream(:body)) do # same as the 'title' method above end end module_function :body end |
When a PO was given, an Expander object will be generated from Template Spec. And the Expander object will generate HTML output using the TO module.
There are many Expander object classes. The selection of Expander class and compiled result of Ruby TO module will be controled by Template Spec.
You can controle the Ruby code with Specs and Expander, but there is always an overhead of Expander because the Expander does not know the type of the PO data so it must check the type of it and select the usage of the module
If you want to pass the overhead of Expander, you can use the TO module direct.
This is good when the speed or detailed controle of usage of the TO module was needed.
We call it 'active PO method'.
--- ../sample/hello/step4.rb --- |
require "amrita2/template" include Amrita2 class PO def passive "passive PO method" end def active(m) m.active("active PO method can replace attrs", :href=>"http://www.ruby-lang.org/") end def active_with_proc proc do |m| m.active_with_proc("output in a Proc") end end def active_nest(m) m.active_nest do |mm| mm.nested("active PO method can ") mm.nested("call dynamic element method ") mm.nested("many times") end end end tmpl = TemplateText.new <<-END <html> <body> <h1>passive method</h1> <span id='passive'> </span> <h1>active method</h1> <a id='active'> </a> <div id='active_with_proc'> </div> <h1>active nested</h1> <p id='active_nest'> <span id='nested' /> </p> </body> </html> END tmpl.expand(STDOUT, PO.new) |
<html> <body> <h1>passive method</h1> <span>passive PO method</span> <h1>active method</h1> <a href='http://www.ruby-lang.org/'>active PO method can replace attrs</a> <div>output in a Proc</div> <h1>active nested</h1> <p> <span>active PO method can </span><span>call dynamic element method </span><span>many times</span> </p> </body> </html> |
If a PO method has a parameter, it will be regarded as an active PO method to which TO passes a Module compiled from the template. The active PO method calls a method of it to produce an output.
def active(m) m.active("active PO method can replace attrs", :href=>"http://www.ruby-lang.org/") end |
Using this mechanisim, you can use many feature of Amrita2. Most usable one is setting an attribute.
<h1>active method</h1> <a href='http://www.ruby-lang.org/'>active PO method can replace attrs</a> |
If the element has inner structures
<h1>active nested</h1> <p id='active_nest'> <span id='nested' /> </p> |
The active PO method should call the method of the template module with a Block.
def active_nest(m) m.active_nest do |mm| mm.nested("active PO method") end end |
Then another Module for inner element will be passed. You can call the methods for inner elements.
<h1>active nested</h1> <p> <span>active PO method</span> </p>
You can call the method of template module any times
def active_nest(m) m.active_nest do |mm| mm.nested("active PO method can ") mm.nested("call dynamic element method ") mm.nested("many times") end end |
Then output is
<h1>active nested</h1> <p> <span>active PO method can </span> <span>call dynamic element method </span> <span>many times</span> </p> |
If you don't call the method in an active PO method, then there will be no output.