Skip to content

Commit e3196a2

Browse files
committed
Dedent: fixed indentation preservation for paired tags inside HTML
1 parent 5d932e2 commit e3196a2

2 files changed

Lines changed: 23 additions & 3 deletions

File tree

src/Latte/Compiler/TemplateParser.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,11 @@ private function applyDedent(FragmentNode $fragment, Tag $startTag): void
513513
$baseIndent = null;
514514
$atLineStart = true;
515515
$inlineChecked = false;
516+
$root = $startTag;
517+
while ($root->parent !== null) {
518+
$root = $root->parent;
519+
}
520+
$tagIndentLen = $root->position->column - 1;
516521

517522
foreach ($fragment->children as $i => $child) {
518523
if ($child instanceof Nodes\TextNode && $child->content === '') {
@@ -545,12 +550,15 @@ private function applyDedent(FragmentNode $fragment, Tag $startTag): void
545550
if ($hasContent) {
546551
preg_match('/^([ \t]+)/', $line, $m);
547552
$baseIndent = $m[1] ?? null;
548-
if ($baseIndent === null) {
549-
return; // first content line has no indent
553+
if ($baseIndent === null || strlen($baseIndent) <= $tagIndentLen) {
554+
return; // first content line has no indent beyond tag level
550555
}
551556

552557
} elseif ($continuesWithExpr) {
553558
$baseIndent = $line;
559+
if (strlen($baseIndent) <= $tagIndentLen) {
560+
return;
561+
}
554562

555563
} else {
556564
continue; // blank line before detection
@@ -564,7 +572,7 @@ private function applyDedent(FragmentNode $fragment, Tag $startTag): void
564572
continue; // blank line, strip silently
565573
}
566574

567-
$line = substr($line, strlen((string) $baseIndent));
575+
$line = substr($line, 0, $tagIndentLen) . substr($line, strlen((string) $baseIndent));
568576
}
569577

570578
unset($line);

tests/common/dedent.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ test('expressions with OutputKeepIndentation and varying indent (issue #413)', f
115115
});
116116

117117

118+
test('foreach inside HTML - dedents only excess indentation', function () {
119+
$result = dedent("<ul>\n\t{foreach \$items as \$item}\n\t\t<li>{\$item}</li>\n\t{/foreach}\n</ul>", ['items' => ['a', 'b']]);
120+
Assert::same("<ul>\n\t<li>a</li>\n\t<li>b</li>\n</ul>", $result);
121+
});
122+
123+
124+
test('nested foreach/if inside HTML', function () {
125+
$result = dedent("<ul>\n\t{foreach [0, 1, 2] as \$item}\n\t\t{if \$item}\n\t\t\t<li>{\$item}</li>\n\t\t{/if}\n\t{/foreach}\n</ul>");
126+
Assert::same("<ul>\n\t<li>1</li>\n\t<li>2</li>\n</ul>", $result);
127+
});
128+
129+
118130
test('inconsistent indentation throws exception', function () {
119131
Assert::exception(
120132
fn() => dedent("{if true}\n\tHello\nWorld\n{/if}"),

0 commit comments

Comments
 (0)