Skip to content

n:attribute Support in php-to-latte.php - #4

Open
NoNoNo wants to merge 1 commit into
nette:masterfrom
NoNoNo:n-attribs
Open

n:attribute Support in php-to-latte.php#4
NoNoNo wants to merge 1 commit into
nette:masterfrom
NoNoNo:n-attribs

Conversation

@NoNoNo

@NoNoNo NoNoNo commented Mar 18, 2026

Copy link
Copy Markdown

Summary

This PR significantly enhances the php-to-latte.php converter with intelligent n:attribute notation support, conditional attribute handling, and nested if optimization. The converter now produces cleaner, more idiomatic Latte templates.

Changes Overview

1. n:attribute Notation for Control Structures (LattePrinter.php)

Control structures that wrap single HTML elements are now converted to n:attribute notation:

Before:

{if $user}
    <div>{$user->name}</div>
{/if}

After:

<div n:if="$user">{$user->name}</div>

Supported structures:

  • {if}n:if
  • {elseif}n:elseif
  • {else}n:else
  • {foreach}n:foreach
  • {for}n:for
  • {while}n:while
  • {try}n:try

2. Conditional Attributes to n:attr (PhpConverter.php)

PHP templates with conditional output inside HTML attributes are now converted to n:attr notation:

Input:

<input type="text" value="<?php if (isset($a)) { echo $a->b; } ?>" />

Output:

<input type="text" n:attr="value: $a->b" />

Features:

  • Supports isset() and !empty() conditions
  • Works with property access ($obj->property), array access ($arr['key']), and simple variables
  • Each attribute gets its own n:attr (cleaner output)
  • Multiple attributes can be processed iteratively

3. Nested If Merging (PhpConverter.php)

Nested if statements are automatically merged into a single condition:

Input:

<?php if ($a) : ?>
    <?php if (isset($b)) : ?>
        <span>...</span>
    <?php endif; ?>
<?php endif; ?>

Output:

<span n:if="$a && isset($b)">...</span>

4. Enhanced String to HTML Conversion (PhpConverter.php)

The stringToHtml() transformation now handles:

  • Simple string echoes
  • Encapsed strings with embedded variables
  • Concatenation expressions (echo '<div>' . $var . '</div>')
  • Simple variable and property echoes (echo $user->id)

5. Self-Closing Element Support (LattePrinter.php)

Void/self-closing HTML elements (<input>, <br>, <img>, etc.) are now properly detected for n:attribute conversion even without closing tags.

Files Changed

  • src/PhpConverter.php (+694 lines)

    • Added convertConditionalAttributes() - transforms conditional attributes to n:attr
    • Added mergeNestedIfs() - merges nested if statements
    • Enhanced stringToHtml() - better echo to HTML conversion
    • Enhanced expandConcat() - skips concatenations with string literals
  • src/LattePrinter.php (+598 lines)

    • Added n:attribute generation for if/elseif/else/try
    • Added n:attribute generation for foreach/for/while
    • Added canGenerateNAttribute*() helpers
    • Added self-closing element detection
    • Added HTML pattern detection for complex elements
  • tests/fixtures-php/n-attributes - 9 new tests

Test Results

all pass

Backward Compatibility

The changes are backward compatible - existing conversions that don't match the new patterns continue to work as before. The new features are additive optimizations.

Examples

Example 1: Simple conditional input

<input value="<?php if (isset($name)) echo $name; ?>" />

<input n:attr="value: $name" />

Example 2: Control structure wrapping element

<?php if ($showError) : ?>
    <div class="error">Error!</div>
<?php endif; ?>

<div n:if="$showError" class="error">Error!</div>

Example 3: Nested ifs

<?php if ($enabled) : ?>
    <?php if ($items) : ?>
        <ul>...</ul>
    <?php endif; ?>
<?php endif; ?>

<ul n:if="$enabled && $items">...</ul>

Example 4: Loop with single element

<?php foreach ($users as $user) : ?>
    <li><?php echo $user->name; ?></li>
<?php endforeach; ?>

<li n:foreach="$users as $user">{$user->name}</li>

Example 5: Try-catch with single element

<?php try : ?>
    <div>Success content</div>
<?php catch (Exception $e) : ?>
    <div>Error occurred</div>
<?php endtry; ?>

<div n:try>Success content</div>
<div n:else>Error occurred</div>

Technical Details

AST Transformation Pipeline

The conversion pipeline in PhpConverter::convert() now runs:

  1. expandEcho() - Split multiple echoes
  2. removeHtmlSpecialChars() - Remove redundant htmlspecialchars
  3. expandConcat() - Expand non-HTML concatenations
  4. removeHtmlSpecialChars() - Second pass
  5. mergeNestedIfs() - Merge nested if statements (NEW)
  6. convertConditionalAttributes() - Transform conditional attributes (NEW)
  7. stringToHtml() - Convert string echoes to HTML

Pattern Detection

The converter uses AST analysis to detect patterns:

  • Single HTML element: One InlineHTML statement
  • HTML pattern: Opening tag + content + closing tag (or self-closing)
  • Conditional attribute: InlineHTML ending with attr=" + If with isset/!empty + InlineHTML starting with "

Future Improvements

Potential future enhancements:

  • Support for n:else with n:attr attributes
  • More complex conditional attribute patterns (ternary operators)
  • Detection and optimization of {first}/{last} patterns
  • Support for n:ifset (Latte 3.x specific)

**Supported structures:**
- `{if}` → `n:if`
- `{elseif}` → `n:elseif`
- `{else}` → `n:else`
- `{foreach}` → `n:foreach`
- `{for}` → `n:for`
- `{while}` → `n:while`
- `{try}` → `n:try`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant