Build your own traditional template engine using Transphporm - Level-2/Transphporm GitHub Wiki

Building a traditional template engine using Transphporm

Transphporm can be used to build your own mini template system where you do place your logic in the template.

Although this is discouraged, this example shows how flexible Transphporm can be.

Including data

The most basic feature a template system needs is a method of replacing content on the page with data. E.g. a marker for displaying the name of the logged in user

With transphporm this would normally be handled by targeting the element that needs replacing. For example:

<header>
   <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="about/">About</a></li>
            <li><a href="contact/">Contact</a></li>
        <ul>

        <p>Welcome back <a class="accountname" href="profile/">Account Name</a>, 
           you have <a class="messages" href="/messages">num</a> new messages</p>
   </nav>
</header>

layout.html

Transphporm would then replace the account name using

.accountname {
   content: data(accountname);
}

.messages {
    content: data(messagecount);
}

layout.tss

And it would be compiled using the PHP code

$template = new \Transphporm\Builder('layout.xml', 'layout.tss');
$template->output(['accountname' = > $_SESSION['login'], 'messagecount' => 5]);

This could be expressed using a traditional template engine using code similar to:

<header>
   <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="about/">About</a></li>
            <li><a href="contact/">Contact</a></li>
        <ul>

        <p>Welcome back <a class="accountname" href="profile/">{{accountname}}</a>, 
           you have <a class="messages" href="/messages">{{messagecount}}</a> new messages</p>
   </nav>
</header>

The template system would then preg_replace {{accountname}} and {{messagecount}}. Although Transphporm cannot do a textual find/replace it can achieve the same thing using elements. Using Transphporm you could create elements which will be replaced.

We'll create the element var and replace it later on:

<header>
   <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="about/">About</a></li>
            <li><a href="contact/">Contact</a></li>
        <ul>

        <p>Welcome back <a class="accountname" href="profile/"><var data="accountname" /></a>, 
           you have <a class="messages" href="/messages"><var data="messagecount" /></a> new messages</p>
   </nav>
</header>

Then, a generic TSS stylesheet can be applied to every page and used to replace any <var> element:

var {
  content: data(attr(data));
  content-mode: replace;
}

n.b. the PHP code that assigns the data would be the same as above

Breaking this down:

var targets every var element on the page

attr(data) reads the contents of the data attribute for the var element (in our example, this will either resolve to accountname or messagecount).

data(attr(data)) takes the value for the data attribute and passes it to the data function, this will be equivalent to data(accountname) or data(messagecount) which will then be set to the content of the element

content-mode: replace tells Transphporm to replace the matched <var> element with the data from the content attribute, rather than the default behaviour setting the element's content.

Conditional logic

Perhaps we only want to display the log in message if the user is logged in, let's add another element called <if> with the attributes val1 and equals:

<header>
   <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="about/">About</a></li>
            <li><a href="contact/">Contact</a></li>
        <ul>

        <if data="loggedin" equals="true">
        <p>Welcome back <a class="accountname" href="profile/"><var data="accountname" /></a>, 
           you have <a class="messages" href="/messages"><var data="messagecount" /></a> new messages</p>
        </if>
   </nav>
</header>

Then add the TSS to check the condition:

if[equals]:data[attr(data)=attr(equals)] { 
   content-mode: replace;
   content: content();
}

This selector will match any <if> element where the contents of the data attribute match the contents of the equals attribute.

Breaking this down:

if[equals] selects any if element with an equals attribute.

attr(data) reads the content of the if element's data attribute.

attr(equals) reads the content of the if element's equals attribute

:data[attr(data)=attr(equals)] will resolve to, for example :data[loggedin=true]

content: content() sets the content of the element to the current content of the element

content-mode: replace tells transphporm to replace the entire if block with its contents

notequals could be implemented in a similar way:

if[notequals]:data[attr(data)!=attr(notequals)] { 
   content-mode: replace;
   content: content();
}

And then use the if element with data and equals elements.

⚠️ **GitHub.com Fallback** ⚠️