=head1 NAME

Template::Semantic::Cookbook - Template::Semantic Recipes

=head1 RECIPES

=head2 Zebra tables

Use XPath power:

  print Template::Semantic->process(\*DATA, {
      'table tbody tr' => [
          { '//td[1]' => '101', '//td[2]' => '102' },
          { '//td[1]' => '201', '//td[2]' => '202' },
          { '//td[1]' => '301', '//td[2]' => '302' },
          { '//td[1]' => '401', '//td[2]' => '402' },
      ],
  })->process({
      '//table//tr[position() mod 2 = 0]/@class' => 'even',
  });
  
  __DATA__
  <table>
      <thead>
          <tr>
              <th>Foo</th>
              <th>Bar</th>
          </tr>
      </thead>
      <tbody>
          <tr class="">
              <td>sample</td>
              <td>sample</td>
          </tr>
      </tbody>
  </table>

Output:

  <table>
      <thead>
          <tr>
              <th>Foo</th>
              <th>Bar</th>
          </tr>
      </thead>
      <tbody>
          <tr class="">
              <td>101</td>
              <td>102</td>
          </tr>
          <tr class="even">
              <td>201</td>
              <td>202</td>
          </tr>
          <tr class="">
              <td>301</td>
              <td>302</td>
          </tr>
          <tr class="even">
              <td>401</td>
              <td>402</td>
          </tr>
      </tbody>
  </table>

If you don't like C<class="">, do this.

  print Template::Semantic->process(\*DATA, {
      ...
  )->process({
      '//table//tr[position() mod 2 = 0]/@class' => 'even',
      '//table//tr[position() mod 2 = 1]/@class' => undef,
  });


=head2 Add attribute

The following example is output with NOT C<< <div class="foo">foo</div> >>
like C<< <div>foo</div> >> because LibXML cannot find C<class> attribute
in C<< <div> >>.

  print Template::Semantic->process(\'<div>foo</div>', {
      'div@class' => 'foo',
  });

Solution:

  print Template::Semantic->process(\'<div>foo</div>', {
      'div' => sub { shift->setAttribute(class => 'foo'); \$_ },
  });

Or:

  print Template::Semantic->process(\'<div class="">foo</div>', {
      'div@class' => 'foo',
  });


=head2 Remove dummy items

Template (includes dummy items to check design):

  <ul>
      <li>sample</li>
      <li class="dummy">sample</li>
      <li class="dummy">sample</li>
      <li class="dummy">sample</li>
  </ul>

Code:

  print Template::Semantic->process($template, {
      '.dummy' => undef, # remove dummys first
  })->process({
      'ul li' => [
          { '/li' => 'AAA' },
          { '/li' => 'BBB' },
          { '/li' => 'CCC' },
          { '/li' => 'DDD' },
      ],
  });


=head2 Remove indicator used only for Temlate::Semantic

Use your own attribute:

  print Template::Semantic->process(\*DATA, {
      '//*[@data-id="foo"]' => 'foo',
      '//*[@data-id="bar"]' => 'bar',
  })->process({
      '//@data-id' => undef,
  });
  
  __DATA__
  <div>
      <span data-id="foo">xxx</span>
      <span data-id="bar">xxx</span>
  </div>

Or:

  print Template::Semantic->process(\*DATA, {
      '.x-foo' => 'foo',
      '.x-bar' => 'bar',
  })->process({
      '//span[contains(@class,"x-")]/@class' => sub {
          join " ", grep { !/^x-/ } split /\s+/;
      },
  });
  
  __DATA__
  <div>
      <span class="x-foo">xxx</span>
      <span class="x-bar">xxx</span>
  </div>


=head2 Some custom filter ideas...

Set output format in template:

  print Template::Semantic->process(\*DATA, {
      '.date' => sub {
          my $date = localtime; # or DateTime->now
          $date->strftime( shift->getAttribute('data-format') );
      },
  })->process({
      '//@data-format' => undef,
  });
  
  __DATA__
  <div class="entry">
      <div class="date" data-format="%Y/%m/%d">2010/99/99</div>
  </div>

Output:

  <div class="entry">
      <div class="date">2010/02/08</div>
  </div>

Another sample:

  use Text::Markdown;
  
  my $ts = Template::Semantic->new;
  $ts->define_filter(markdown => sub { \ Text::Markdown::markdown($_) });
  
  print $ts->process(\*DATA, {
      'div.content' => sub {
          $ts->call_filter( shift->getAttribute('data-format') );
      },
  })->process({
      '//@data-format' => undef,
  });
  
  __DATA__
  <div class="container">
      <div class="content" data-format="markdown">
          *bla* bla bla
      </div>
      <div class="content" data-format="html_line_break">
          bla bla bla
      </div>
  </div>


=head1 Do you have another good usage?

Blog it ;)


=head1 AUTHOR

Naoki Tomita E<lt>tomita@cpan.orgE<gt>

=cut

