Zope Page Templates (ZPT)
=========================

This test demonstrates the compilation of TAL and METAL attribute
languages.

TAL
---
  
:: Namespace elements

  >>> print render("""\
  ... <tal:block xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   Hello, world!
  ... </tal:block>""")
  <BLANKLINE>
    Hello, world!
  <BLANKLINE>

tal:define, tal:attributes, tal:content, tal:replace
  
  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...  <span tal:define="a 'abc'" tal:content="a" />
  ...  <span tal:define="b 'def'"><span tal:replace="b" /></span>
  ...  <span tal:content="a|None" />
  ...  <span tal:content="b|None" />
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
   <span>abc</span>
   <span>def</span>
  </div>
  
  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <span id="test"
  ...         class="dummy"
  ...         onclick=""
  ...         tal:define="a 'abc'"
  ...         tal:attributes="class 'def' + a + default; style 'hij'; onClick 'alert();'"
  ...         tal:content="a + 'ghi'" />
  ...   <span tal:replace="'Hello World!'">Hello <b>Universe</b>!</span>
  ...   <span tal:replace="'Hello World!'"><b>Hello Universe!</b></span>
  ...   <span tal:content="None" />
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    <span class="defabcdummy" style="hij" onclick="alert();" id="test">abcghi</span>
    Hello World!
    Hello World!
  </div>

tal:attributes 'checked' and 'selected' toggles

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <option tal:attributes="selected True"></option>
  ...   <option tal:attributes="selected None"></option>
  ...   <input tal:attributes="checked True" />
  ...   <input tal:attributes="checked False" />
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
     <option selected="True"></option>
     <option></option>
     <input checked="True" />
     <input />
  </div>

tal:repeat
    
  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <ul>
  ...     <li tal:repeat="i range(5)"><span tal:replace="'Item ' + str(i) + ')'" /></li>
  ...   </ul>
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    <ul>
      <li>Item 0)</li>
      <li>Item 1)</li>
      <li>Item 2)</li>
      <li>Item 3)</li>
      <li>Item 4)</li>
    </ul>
  </div>

tal:repeat (repeat-variable)

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <ul>
  ...     <li tal:repeat="i range(3)"><span tal:replace="str(i) + ' ' + str(repeat['i'].even())" /></li>
  ...   </ul>
  ... </div>""")
    <div xmlns="http://www.w3.org/1999/xhtml">
      <ul>
        <li>0 True</li>
        <li>1 False</li>
        <li>2 True</li>
      </ul>
    </div>

tal:condition

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <div tal:condition="True">
  ...     Show me!
  ...   </div>
  ...   <div tal:condition="False">
  ...     Do not show me!
  ...   </div>
  ...   <tal:empty condition="True" />
  ... </div>""")
    <div xmlns="http://www.w3.org/1999/xhtml">
      <div>
        Show me!
      </div>
    </div>

:: TAL elements with namespace prefix

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <tal:example replace="'Hello World!'" />
  ...   <tal:example tal:replace="'Hello World!'" />
  ...   <tal:div content="'Hello World!'" />
  ...   <tal:multiple repeat="i range(3)" replace="i" />
  ...   <tal:div condition="True">True</tal:div>
  ... </div>""")
    <div xmlns="http://www.w3.org/1999/xhtml">
      Hello World!
      Hello World!
      Hello World!
      0
      1
      2
      True
    </div>

tal:omit-tag

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <p tal:omit-tag="">No paragraph here.</p>
  ...   <p tal:omit-tag="True">No paragraph here either.</p>
  ...   <p tal:omit-tag="False">A paragraph here.</p>
  ... </div>""")
    <div xmlns="http://www.w3.org/1999/xhtml">
      No paragraph here.
      No paragraph here either.
      <p>A paragraph here.</p>
    </div>

:: Unicode with dynamic attributes and content
    
  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <img tal:attributes="title '%sHello%s' % (chr(60), chr(62))" />
  ...   <span tal:replace="structure '%sbr /%s' % (chr(60), chr(62))" />
  ...   <span tal:replace="'%sbr /%s' % (chr(60), chr(62))" />
  ...   <span tal:content="unicode('La Pe\xc3\xb1a', 'utf-8')" />
  ... </div>""")
    <div xmlns="http://www.w3.org/1999/xhtml">
      <img title="&lt;Hello&gt;" />
      <br />
      &lt;br /&gt;
      <span>La Peña</span>
    </div>

:: Using the "string:" expression

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <span tal:replace="string:${greeting}, world!" />
  ...   <img tal:attributes="alt string:Leonardo da Vinci;; Musee du Louvre, 1503;
  ...                        title string:Mona Lisa;" />
  ... </div>""", request=object(), greeting=u'Hello')
  <div xmlns="http://www.w3.org/1999/xhtml">
    Hello, world!
    <img alt="Leonardo da Vinci; Musee du Louvre, 1503" title="Mona Lisa" />
  </div>

:: Using different expressions with try-except operator (|)
  
  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...      <span tal:replace="abc|1" />
  ...      <span tal:replace="2|abc" />
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
       1
       2
  </div>

:: Using the "structure" TAL pragma.

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <span tal:replace="structure dir" />
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    <built-in function dir>
  </div>

METAL
-----

metal:define-macro, metal:use-macro

  >>> body = """\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
  ...      xmlns:metal="http://xml.zope.org/namespaces/metal">
  ...   <div class="greeting" metal:define-macro="greeting">
  ...     Hello, <span tal:replace="name|string:earth" />!
  ...   </div>
  ...   <div tal:define="name 'world'">
  ...     <div metal:use-macro="template.macros['greeting']" />
  ...   </div>
  ... </div>"""

  >>> from chameleon.core.testing import MockTemplate
  >>> from chameleon.zpt.language import Parser

  >>> template = MockTemplate(body, Parser())
  >>> print render(body, template=template)
  <div xmlns="http://www.w3.org/1999/xhtml">
    <div class="greeting">
      Hello, earth!
    </div>
    <div>
      <div class="greeting">
      Hello, world!
    </div>
  <BLANKLINE>
    </div>  
  </div>

metal:define-slot, metal:fill-slot

  >>> body = """\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
  ...      xmlns:metal="http://xml.zope.org/namespaces/metal">
  ...   <div class="macro" metal:define-macro="greeting">
  ...     Hey, <span class="name" metal:define-slot="name">
  ...     a <em>stranger!</em></span>
  ...   </div>
  ...   <div metal:use-macro="template.macros['greeting']">
  ...     This will be omitted
  ...     <span class="filled" metal:fill-slot="name">earth!</span>
  ...   </div>
  ...   <div metal:use-macro="template.macros['greeting']">
  ...     This will be omitted
  ...     <span class="filled" metal:fill-slot="name" />
  ...   </div>
  ...   <div metal:use-macro="template.macros['greeting']">
  ...     <input metal:fill-slot="name" type="hidden"
  ...            tal:attributes="value 'hello'" />
  ...   </div>
  ...   <div metal:use-macro="template.macros['greeting']">
  ...     <div>
  ...       <metal:earth fill-slot="name">earth!</metal:earth>
  ...     </div>
  ...   </div>
  ...   <div metal:use-macro="template.macros['greeting']">
  ...     <!-- display fallback greeting -->
  ...   </div>
  ...   <div metal:use-macro="template.macros['greeting']">
  ...     <span metal:fill-slot="dummy">dummy!</span>
  ...   </div>
  ... </div>"""

  >>> template = MockTemplate(body, Parser())
  >>> print render(body, template=template)
  <div xmlns="http://www.w3.org/1999/xhtml">
    <div class="macro">
      Hey, <span class="name">
      a <em>stranger!</em></span>
    </div>
    <div class="macro">
      Hey, <span class="filled">earth!</span>
    </div>
    <div class="macro">
      Hey, <span class="filled" />
    </div>
    <div class="macro">
      Hey, <input value="hello" type="hidden" />
    </div>
    <div class="macro">
      Hey, earth!
    </div>
    <div class="macro">
      Hey, <span class="name">
      a <em>stranger!</em></span>
    </div>
    <div class="macro">
      Hey, <span class="name">
      a <em>stranger!</em></span>
    </div>
  </div>

Expression interpolation
------------------------

The ``chameleon.zpt`` parser supports Genshi interpolation
expressions.

Outside tags:

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   Interpolation ${'expressions'} are ${'convenient'}.
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    Interpolation expressions are convenient.
  </div>

Inside tags:

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <img alt="Interpolation ${'expressions'} are ${'convenient'}" />
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    <img alt="Interpolation expressions are convenient" />
  </div>

We can disable this feature using ``meta:interpolation``::

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:tal="http://xml.zope.org/namespaces/tal"
  ...      xmlns:meta="http://xml.zope.org/namespaces/meta">
  ...   <div meta:interpolation="false">
  ...     ${'foo'}
  ...   </div>
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    <div>
      ${'foo'}
    </div>
  </div>

The ``tail`` of an element does get intepolated depending oon
it's parent::

  >>> print render("""\
  ... <div xmlns="http://www.w3.org/1999/xhtml"
  ...      xmlns:meta="http://xml.zope.org/namespaces/meta">
  ...   <div meta:interpolation="false">
  ...     ${nope}
  ...   </div>
  ...   ${'interpolation'}
  ...   <div>
  ...     ${'interpolation'}
  ...     <span meta:interpolation="false">
  ...       ${nope}
  ...       <span meta:interpolation="true">
  ...         ${'interpolation'}
  ...       </span>
  ...       ${'nope'}
  ...     </span>
  ...   </div>
  ... </div>""")
  <div xmlns="http://www.w3.org/1999/xhtml">
    <div>
      ${nope}
    </div>
    interpolation
    <div>
      interpolation
      <span>
        ${nope}
        <span>
          interpolation
        </span>
        ${'nope'}
      </span>
    </div>
  </div>

Escaping inserted data
----------------------
By default all inserted data is escaped::

  >>> print render("""\
  ... <html xmlns="http://www.w3.org/1999/xhtml"
  ...       xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <body>
  ...     <span tal:content="data">Data</span>
  ...     <span tal:replace="data">Data</span>
  ...     ${data}
  ...   </body>
  ... </html>""", data="one & two")
  <html xmlns="http://www.w3.org/1999/xhtml">
    <body>
      <span>one &amp; two</span>
      one &amp; two
      one &amp; two
    </body>
  </html>


If inserted data has a __html__ method it is called and the result is
inserted without further escaping:

  >>> class Markup(unicode):
  ...     def __html__(self):
  ...         return self
  
  >>> print render("""\
  ... <html xmlns="http://www.w3.org/1999/xhtml"
  ...       xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <body>
  ...     <span tal:content="data">Data</span>
  ...     <span tal:replace="data">Data</span>
  ...     ${data}
  ...   </body>
  ... </html>""", data=Markup("<em>correct</em>"))
  <html xmlns="http://www.w3.org/1999/xhtml">
    <body>
      <span><em>correct</em></span>
      <em>correct</em>
      <em>correct</em>
    </body>
  </html>

If validation is enabled, markup inserted using ``__html__`` must
validate

  >>> from chameleon.core import config
  >>> config.VALIDATION = True
  
  >>> print render("""\
  ... <html xmlns="http://www.w3.org/1999/xhtml"
  ...       xmlns:tal="http://xml.zope.org/namespaces/tal">
  ...   <body>
  ...     ${data}
  ...   </body>
  ... </html>""", data=Markup("<em>incorrect<em>"))
  Traceback (most recent call last):
   ...
  ValidationError: Insertion of u'<em>incorrect<em>' is not allowed.
  
  >>> config.VALIDATION = False
