pad

PAD Constructs Reference

This document provides a complete reference for all PAD constructs - special @something@ markers used in PAD templates.

Overview

PAD constructs are special placeholder markers that control template structure and content flow. They use the @name@ syntax and are processed during template building and rendering.

@page@
@content@
@start@
@end@
@else@
@tidy@

Template Structure Constructs

@page@

The main content placeholder that marks where page content should be inserted.

Purpose: Central insertion point for page content in the template hierarchy.

Usage:

<!DOCTYPE html>
<html>
<head><title>My App</title></head>
<body>
  @page@
</body>
</html>

Behavior:

Build Process (see build/base.php and build/build.php):

  1. Starts with @page@ as the base
  2. Each directory’s _inits.pad and _exits.pad wrap around it
  3. Final page content replaces @page@

Example with Init/Exit:

<!-- _inits.pad -->
<html><body>
@page@

<!-- _exits.pad -->
</body></html>

<!-- Result: <html><body> [page content] </body></html> -->

@content@

Content merge placeholder for inserting content into parent templates.

Purpose: Marks where child content should be merged into parent content.

Usage:

<!-- _tags/article.pad - used as {article}<p>child</p>{/article} -->
<article>
  <header>Article Header</header>
  @content@
  <footer>Article Footer</footer>
</article>

Behavior:

Merge Options (merge=, when neither side holds an @content@):


Processing Control Constructs

@start@

Start marker: what stands before it is a prelude, rendered once before the rows.

Purpose: Splits a tag’s content into a prelude, the body that renders per row, and - with @end@ - a coda.

Usage:

{myTag}
  <header>once, before the rows</header>
  @start@
  <li>per row</li>
  @end@
  <footer>once, after the rows</footer>
{/myTag}

Behavior:

Use Cases:


@end@

End marker: what stands after it is a coda, rendered once after all rows.

Purpose: Closes the per-row body that @start@ opened.

Usage: see @start@ above - the two are written together.

Behavior:

Use Cases:


@else@

True/false branch separator inside a tag’s content.

Purpose: Splits a tag’s content into a “truthy” part and a fallback part - a compact alternative to the {else} tag.

Usage:

{if $hasEntries}
  {entries}
    <div>{$name}: {$comment}</div>
  {/entries}
@else@
  <p>No entries yet. Be the first to sign!</p>
{/if}

Behavior:


Output Control Constructs

@tidy@

Tidy marker that triggers HTML output formatting.

Purpose: Signals that HTML tidying should be applied to the output.

Usage:

@tidy@
<html>
<head><title>Page</title></head>
<body>
  <div><p>Content</p></div>
</body>
</html>

Behavior:

Tidying Effects:


Construct Summary Table

Construct Purpose Replaced With
@page@ Main content placeholder Page content
@content@ Content merge point Child content
@start@ End of the prelude, start of the per-row body Split marker
@end@ End of the per-row body, start of the coda Split marker
@else@ True/false branch separator Split marker
@tidy@ HTML formatting trigger Removed (triggers tidy)

Construct Files

Constructs are registered by files in PAD/constructs/:

File Construct
page.php @page@
content.php @content@
start.php @start@
end.php @end@
else.php @else@
tidy.php @tidy@

The files are a registry, never included: under the strict check, when the page is built (build/build.php), an @word@ of the template without its file here is an error - “there is no @foo@ construct”. Text inside {ignore} is not read.


Usage Examples

Page Layout with Init/Exit

_inits.pad:

<!DOCTYPE html>
<html>
<head>
  <title>{$pageTitle}</title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <nav>{include:navigation}</nav>
  <main>
@page@

_exits.pad:

  </main>
  <footer>{include:footer}</footer>
</body>
</html>

Content Merging

Parent template (_tags/layout.pad):

<div class="container">
  <aside class="sidebar">{include:sidebar}</aside>
  <article class="content">
    @content@
  </article>
</div>

Child content, in a page:

{layout}
  <h1>Page Title</h1>
  <p>Page content goes here...</p>
{/layout}

Empty-Data Fallback

{entries}
  <div>{$name}: {$comment}</div>
@else@
  <p>No entries found.</p>
{/entries}

Two-Phase Processing

{users}
  {-- Header processed first --}
  <table>
    <tr><th>Name</th><th>Email</th></tr>
  @start@
  {-- Rows processed with data --}
    <tr><td>{$name}</td><td>{$email}</td></tr>
  @end@
  {-- Footer processed last --}
  </table>
  <p>Total: {count@users} users</p>
{/users}

Conditional Tidy

{if $debug eq 1}
  @tidy@
{/if}
<html>
  <!-- HTML will be tidied only in debug mode -->
</html>

Processing Order

  1. Build Phase: Init/exit wrapping around @page@
  2. Build Phase: @page@ replaced with page content
  3. Render Phase: @start@, @end@ and @else@ splitting
  4. Render Phase: @content@ merging
  5. Exit Phase: @tidy@ detection and HTML tidying