
require 'rexml/document'
require 'amrita2'
require 'amrita2/testsupport'

context "Simple Template" do
  include Amrita2

  specify "XML template" do
    #
    # Template for Amrita2 is basically well-formed xml/xhtml file
    # with am:src attributes specifying dynamic elements.
    #
    t = Amrita2::Template.new <<-END
      <html>
        <head>
          <title am:src="page_title" />
       </head>
       <body>
         <h1 am:src="header_title" />
          <p class="text" am:src="text">
             <span am:src="template" /> is a html template library for <span am:src="lang" />
         </p>
       </body>
      </html>
    END

    #
    # A Ruby Hash or almost any data in Ruby can be model data for rendering dynamic element.
    #
    data = { 
      :page_title=>'Amrita2',
      :header_title=>'Hello, Amrita2',
      :text=>{
        :template => 'Amrita2',
        :lang => 'Ruby'
      }
    }

    # This is output
    expected = <<-END
      <html>
      <head>
        <title>Amrita2</title>
      </head>
      <body>
        <h1>Hello, Amrita2</h1>
        <p class="text">Amrita2 is a html template library for Ruby</p>   
      </body>
      </html>
    END
    
    t.render_with(data).should_be_samexml_as(expected)

    #
    # Amrita2 has an alternate indent based format for template: AMXML
    #
    t2 = Amrita2::Template.new <<-END
      <<html<
        <<head<
          <<title:page_title>>
        <<body<
          <<h1 :header_title>>
          <<p.text :text<
             <<:template>> is a html template library for <<:lang>>
    END
    
    # Same result
    t2.render_with(data).should_be_samexml_as(expected)
  end
end

context "erb" do
  include Amrita2::Runtime
  include Amrita2
  
  specify "simple erb" do
    # You can mix erb elements in Amrita2 templates
    t = Amrita2::Template.new <<-'END'
      <%= 1 + 2 %>
    END
    t.render_with(binding).should_be_samexml_as " 3 "
  end
  
  specify "all CDATA will be evaluated as erb" do
    t = Amrita2::Template.new <<-'END'
      <![CDATA[
        <%
           cls = 'xxx'
           a = 1
         %>
        <div class="<%= cls %>">
          1 + 2 = <%= a + 2 %>
        </div>
      ]]>
    END
    t.render_with(binding).should_be_samexml_as "<div class='xxx'>1 + 2 =  3</div>"
  end
  
  specify "erb using context data" do
    #
    # In ERb elements in Amrita2, the context data will be passed
    # as $_ variable.
    #
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <<:list<
        <li><%= $_ * 10 %></li>
    END
    list = [1..3]
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>10</li>
        <li>20</li>
        <li>30</li>
      </ul>
    END
  end
  
  specify "erb providing context data" do

    # If the context data is binding,
    # you can set a context data to a variables for Amrita2 rendering engine
    t = Amrita2::Template.new <<-'END'
    <<ul<
      # Line start with # is a comment line.
      # Line start with % is an ERb element line.   
      % list1 = (1..3).collect { |n| n*10 }
      <<li:list1>>
    END
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>10</li>
        <li>20</li>
        <li>30</li>
      </ul>
    END
  end
  
  specify "erb filtering model data" do
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <<li:list<
        % $_[:no_times10] = $_[:no] * 10 
        <<:no>> * 10  = <<:no_times10>>
    END
    
    list = (1..3).collect do |n|
      { :no => n }
    end
    
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>1 * 10 = 10</li>
        <li>2 * 10 = 20</li>
        <li>3 * 10 = 30</li>
      </ul>
    END
  end

  HashDelegator = Amrita2::HashDelegator
  
  specify "erb filtering model data with amxml" do
    t = Amrita2::Template.new <<-'END'
    <<ul<
      <<:list <
        <<li ?[($_[:no]%2) != 0 ] <
          # "<< { ... } <" adds members for context data
          <<{
             :no => $_[:no],
             :no_times10 => $_[:no] * 10
             } <
             <<:no>> * 10  = <<:no_times10>>
    END
    
    list = (1..3).collect do |n|
      { :no => n }
    end
    
    t.render_with(binding).should_be_samexml_as <<-END
      <ul>
        <li>1 * 10 = 10</li>
        <li>3 * 10 = 30</li>
      </ul>
    END
  end
end

context "filters" do
  include Amrita2
  include Amrita2::Runtime

  # You can set Filters in dynamic elements.
  specify "Format" do
    t = Amrita2::Template.new <<-END
      <<:a | Format['(%-4.2f)'] >>
    END
    
    t.render_with(:a=>1234.56).should_be_samexml_as('(1234.56)')
  end
  
  specify "Default and Format" do
    t = Amrita2::Template.new <<-END
      <<div<
        <<span.number :a | Default['(0.00)'] | Format['(%-4.2f)'] >>
    END
    t.render_with(:a=>[1234.56,nil,-7890]).should_be_samexml_as <<-END
      <div>
        <span class='number'>(1234.56)</span>
        <span class='number'>(0.00)</span>
        <span class='number'>(-7890.00)</span>
      </div>
    END
  end
end

context "Attribute" do
  include Amrita2
  include Amrita2::Runtime

  setup do 
    @data = {
      :mail=>{
        :no=>142990,
        :title=>"[ANN] Amrita2 1.9.5"
      }
    }

    @expected = <<-EOF
      <a href='http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/142990'>[ruby-talk:142990][ANN] Amrita2 1.9.5</a>
    EOF
  end

  specify "NVar" do
    # NVar filter replaces $1, $2, ... by context data.
    t = Amrita2::Template.new <<-END
      <<a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/$1"
          :mail | NVar[:no,:title] <
        [ruby-talk:$1]$2
    END
    
    t.render_with(@data).should_be_samexml_as(@expected)
  end
  
  specify "Attr with erb" do
    #
    # Attr filter replaces attributes by context data.
    #
    t = Amrita2::Template.new <<-'END'
      <%
        mail = @data[:mail]
        mail[:href] = "http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/#{mail[:no]}"
        mail[:body] = "[ruby-talk:#{@data[:mail][:no]}]#{mail[:title]}"
      %>
      <<a :mail | Attr[:href, :body] >>
    END
    #t.set_trace(STDOUT)
    t.render_with(binding).should_be_samexml_as(@expected)
  end
  
  specify "Attr" do
    t = Amrita2::Template.new <<-'END'
      <<{
          :mm => { 
            :href=>"http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/#{$_[:no]}",
            :body=>"[ruby-talk:#{$_[:no]}]#{$_[:title]}"
          }
         } <
        <<a :mm | Attr[:href, :body] >>
    END
  
    t.render_with(@data[:mail]).should_be_samexml_as(@expected)
  end
  
  specify "Hook" do

    # Using Hook
    t = Amrita2::Template.new <<-'END'
      <<:mail_hook | AcceptData[:hook] <
        <<a :m|Attr[:href, :body]>>
    END

    mail = @data[:mail]

    # Hook object can control rendering
    hook1 = Amrita2::Core::Hook.new do
      href = "http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/#{mail[:no]}"
      body = "[ruby-talk:#{mail[:no]}]#{mail[:title]}"
      render_child(:m, :href=>href, :body=>body)
    end
  
    #t.set_trace(STDOUT)
    t.render_with(:mail_hook=>hook1).should_be_samexml_as(@expected)
  end
end

# http://www.cheetahtemplate.org/examples.html
context "Cheetah's sample" do
  include Amrita2

  setup do
    @t = Amrita2::Template.new <<EOF
<html>
  <head><title am:src="title" /></head>
  <body>
    <table>
      <tr am:src="clients|NVar[:surname, :firstname, :email]">
        <td>$1, $2</td>
        <td><a href="mailto:$3">$3</a></td>
     </tr>
    </table>
  </body>
</html>
EOF
  end
  
  specify "" do
    client = Struct.new(:surname, :firstname, :email)
    data = {
      :title => "Amrita2 sample",
      :clients => [
        client.new("Matsumoto", "Yukihiro", "matz@netlab.co.jp"),
        client.new("Nakajima", "Taku", "tnakajima@brain-tokyo.jp"),
      ]
    }
    @t.render_with(data).should_be_samexml_as <<-EOF
<html>
  <head><title>Amrita2 sample</title></head>
  <body>
    <table>
      <tr>
        <td>Matsumoto, Yukihiro</td>
        <td><a href='mailto:matz@netlab.co.jp'>matz@netlab.co.jp</a></td>
     </tr><tr>
        <td>Nakajima, Taku</td>
        <td><a href='mailto:tnakajima@brain-tokyo.jp'>tnakajima@brain-tokyo.jp</a></td>
     </tr>
    </table>
  </body>
</html>
EOF
  end
end

context "table" do
  #Lang = Struct.new(:name, :author, :website)
  WebSite = Struct.new(:name, :url)

  class Lang
    include Amrita2::DictionaryData
    attr_reader :name, :author, :website
    def initialize(n, a, w)
      @name, @author, @website = n, a, w
    end
  end

  setup do 
    @data = {
      :lang_list =>[ 
        Lang.new("Ruby", "matz", WebSite.new('Ruby Home Page', 'http://www.ruby-lang.org/')),
        Lang.new("Perl", "Larry Wall", WebSite.new('The Source for Perl', 'http://perl.com/')),
        Lang.new("Python","Guido van Rossum", WebSite.new('Python Programing Language', 'http://www.python.org/'))
      ]
    }
  end
  
  specify "simple" do
    # AMXML preprocessor generates TD/TH from a line start with '|'.
    t = Amrita2::Template.new <<-END
    <<table border='1'<
      <<tr:lang_list <
        ||| <<:name>> | <<:author>>|
    END

    t.render_with(@data).should_be_samexml_as <<-END
      <table border = "1">
        <tr><td>Ruby</td><td>matz</td></tr>
        <tr><td>Perl</td><td>Larry Wall</td></tr>
        <tr><td>Python</td><td>Guido van Rossum</td></tr>
      </table>
    END
  end
  
  specify "with title and attributes" do
    t = Amrita2::Template.new <<-END
    <<table border='1'<
      <<tr<------------------------------------------------------------------
        |         || name      ||author     ||cite                         ||
        |class    || h_name    ||h_author   ||h_cite                       ||
        ----------------------------------------------------------------------
      <<tr:lang_list
           |ToHash[:name=>:name, :author=>:author, :site=>:website]
           |Each[:class=>["odd", "even"]]
           |Attr[:class]
        <---------------------------------------------------------------------
        |         || <<:name>> | <<:author>>|<a am:src='site'               |
        |         ||           |            | am:filter='Attr[              |
        |         ||           |            |  :href=>:url, :body=>:name]'/>|
        |class    || name      | author     |site                           |
        ----------------------------------------------------------------------
    END

    #t.set_trace(STDOUT)
    t.render_with(@data).should_be_samexml_as <<-END
      <table border='1'>
        <tr>
          <th class='h_name'>name</th>
          <th class='h_author'>author</th>
          <th class='h_cite'>cite</th>
        </tr>
        <tr class='odd'>
          <td class='name'>Ruby</td>
          <td class='author'>matz</td>
          <td class='site'>
            <a href='http://www.ruby-lang.org/'>Ruby Home Page</a>
          </td>
       </tr>
       <tr class='even'>
          <td class='name'>Perl</td>
          <td class='author'>Larry Wall</td>
          <td class='site'>
            <a href='http://perl.com/'>The Source for Perl</a>
          </td>
       </tr>
       <tr class='odd'>
          <td class='name'>Python</td>
          <td class='author'>Guido van Rossum</td>
          <td class='site'>
            <a href='http://www.python.org/'>Python Programing Language</a>
          </td>
       </tr>
      </table>
    END
  end
  
  specify 'rowspan colspan' do 
    # from http://www.y-adagio.com/public/standards/tr_html4/struct/tables.html
=begin    
    A test table with merged cells
    /-----------------------------------------\
    |          |      Average      |   Red    |
    |          |-------------------|  eyes    |
    |          |  height |  weight |          |
    |-----------------------------------------|
    |  Males   | 1.9     | 0.003   |   40%    |
    |-----------------------------------------|
    | Females  | 1.7     | 0.002   |   43%    |
    \-----------------------------------------/
=end
    expected = <<-END 
    <table border="1"
           summary="This table gives some statistics about fruit
                   flies: average height and weight, and percentage
                   with red eyes (for both males and females).">
      <caption><em>A test table with merged cells</em></caption>
      <tr>
        <th rowspan="2"></th>
        <th colspan="2">Average</th>
        <th rowspan="2">Red<br/>eyes</th>
      </tr>
      <tr>
        <th>height</th>
        <th>weight</th>
      </tr>
      <tr>
        <th>Males</th>
        <td>1.9</td>
        <td>0.003</td>
        <td>40%</td>
      </tr>
      <tr>
        <th>Females</th>
        <td>1.7</td>
        <td>0.002</td>
        <td>43%</td>
      </tr>
    </table>
    END
    t = Amrita2::Template.new <<-END
    <<table border='1':|Attr[:summary]<
      <<caption<
        <<em:caption>>
      <<<-------------------------------------------------------------------------
        | rowspan  || 2      ||                             ||     2         ||
        | colspan  ||        ||         2                   ||               ||
        |          ||        ||         Average             ||Red<br />eyes  ||
      <<<---------------------------------------------------------------------------
        |                    ||           ||                || 
        |                    ||  height   ||weight          ||             
        |                    ||           ||                || 
      <<tr:data<
        |am:src    || sex    ||  height   |  weight         |  percent       |
        |am:filter ||        ||           | Format['%1.3f'] |Format['%d%%']  |
    END

    data = {
      :summary=>"This table gives some statistics about fruit
                   flies: average height and weight, and percentage
                   with red eyes (for both males and females).",
      :caption=>'A test table with merged cells',
      :data => [
        { :sex=>'Males' ,   :height=>1.9, :weight=>0.003, :percent=>40 },
        { :sex=>'Females' , :height=>1.7, :weight=>0.002, :percent=>43 }
      ]
    }
    #puts t.render_with(data)
    t.render_with(data).should_be_samexml_as(expected)
    IO.popen("w3m -T text/html", "r+") do |io|
      io.puts t.render_with(data)
      io.close_write
      #print io.read
    end
  end
end


context "Cheetah's sample with amxml" do
  include Amrita2

  setup do
    @t = Amrita2::Template.new <<EOF
<<html<
  <<head<
    <<title:title>>
  <<body<
    <<table border='1'<
      <<tr:clients|NVar[:surname, :firstname, :email]<
        #-----------------------------------------
        |class||cell1 |cell2                     |
        #-----------------------------------------
        |     ||$1, $2||<a href="mailto:$3">$3</a>|
        #-----------------------------------------
EOF
    @t = Amrita2::Template.new <<'EOF'
<<html<
  <<head<
    <<title:title>>
  <<body<
    <<table border='1'<
      <<tr:clients <
        << {
            :name=>"#{$_[:surname]}, #{$_[:firstname] }",
            :url => "mailto:#{$_[:email]}",
            :mailtext => $_[:email] 
           } <
          #-----------------------------------------
          |class||cell1    | cell2                                      |
          |     ||<<:name>>||<<a:\|Attr[:href=>:url, :body=>:mailtext]>>|
EOF
  end
  
  specify "" do
    client = Struct.new(:surname, :firstname, :email)
    data = {
      :title => "Amrita2 sample",
      :clients => [
        client.new("Matsumoto", "Yukihiro", "matz@netlab.co.jp"),
        client.new("Nakajima", "Taku", "tnakajima@brain-tokyo.jp"),
      ]
    }
    #puts @t.render_with(data)
    @t.render_with(data).should_be_samexml_as <<-EOF
<html>
  <head><title>Amrita2 sample</title></head>
  <body>
    <table border='1'>
      <tr>
        <th class='cell1'>Matsumoto, Yukihiro</th>
        <td class='cell2'><a href='mailto:matz@netlab.co.jp'>matz@netlab.co.jp</a></td>
     </tr><tr>
        <th class='cell1'>Nakajima, Taku</th>
        <td class='cell2'><a href='mailto:tnakajima@brain-tokyo.jp'>tnakajima@brain-tokyo.jp</a></td>
     </tr>
    </table>
  </body>
</html>
EOF
    
=begin    
    IO.popen("w3m -dump -T text/html", "r+") do |io|
      io.puts @t.render_with(data)
      io.close_write
      print io.read
    end
=end
  end
end

# http://d.hatena.ne.jp/tokuhirom/20070110/1168416921
context "TT's sample" do
  include Amrita2
  include Amrita2::Runtime
  setup do
    @t = Amrita2::Template.new <<EOF
<table border="0">
<tr
    am:for="colors.keys.sort"
    am:v="{ :name => $_ , :color => colors[$_] }"
>
  <td
      am:v='{:bgcolor => colors["white"], :body=> $_}'
      am:filter="Attr[:bgcolor, :body]"
  >
    <b am:src='body'><span am:src='name'/></b>
  </td>
  <td
      am:v='{:bgcolor => $_[:color] }'
      am:filter="Attr[:bgcolor, :body]"
  >
    <span
      am:v='"&nbsp"'
      am:filter="NoSanitize | Repeat[5]"
    />
  </td>
  <td
      am:v='{:bgcolor => colors["white"] , :body=> $_[:color]}'
      am:filter="Attr[:bgcolor, :body]"
  >
  </td>
</tr>
</table>
EOF
  end
  
  specify "" do
    @t.inline_ruby = true
    colors = {
      'white' => '#FFFFFF',
      'black' => '#000000',
    }
    @t.render_with(binding).should_be_samexml_as <<-EOF
<table border = "0">
<tr>
  <td bgcolor='#FFFFFF'>
    <b>black</b>
  </td>
  <td bgcolor='#000000'>
    &nbsp&nbsp&nbsp&nbsp&nbsp
  </td>
  <td bgcolor='#FFFFFF'>#000000</td>
</tr><tr>
  <td bgcolor='#FFFFFF'>
    <b>white</b>
  </td>
  <td bgcolor='#FFFFFF'>
    &nbsp&nbsp&nbsp&nbsp&nbsp
  </td>
  <td bgcolor='#FFFFFF'>#FFFFFF</td>
</tr>
</table>
EOF
  end
end

