Skip to content

Instantly share code, notes, and snippets.

@rodneyrehm
Created March 7, 2012 17:36
Show Gist options
  • Save rodneyrehm/1994582 to your computer and use it in GitHub Desktop.
Save rodneyrehm/1994582 to your computer and use it in GitHub Desktop.
Smarty: Whitespace Control
<?php
$string = '{foreach $element->children as $c}
{-if $c->max_count == 1}
{-$c->getClassName()} {$c->getMemberVariableName()-};
{-else-}
{$c->getClassName()} {$c->getMemberVariableName()};
std::vector<{$c->getClassName()}> {$c->getMemberVariableName()}s;
{-/if-}
{-/foreach} hello
{--sometag}
{-+sometag}';
/*
{-tag} remove white space infront of tag up to the previous non-whitespace character or beginning of the line
"text \n\n\t {-tag}" -> "text \n\n{tag}"
"text \n\n\t text\t {-tag}" -> "text \n\n\t text{tag}"
{--tag} remove white space infront of tag up to the previous non-whitespace character
"text \n\n\t {--tag}" -> "text{tag}"
"text \n\n\t text\t {--tag}" -> "text \n\n\t text{tag}"
{+-tag}
{-+tag} replace white space infront of tag up to the previous non-whitespace character by a single line-break
"text \n\n\t {-+tag}" -> "text\n{tag}"
"text \n\n\t text\t {-+tag}" -> "text \n\n\t text\n{tag}"
{tag-} remove white space after tag up to the next non-whitespace character or end of the line
"{tag-} \n\n\t text" -> "{tag}\n\n\t text"
"{tag-} text \n\n\t text" -> "{tag}text \n\n\t text"
{tag--} remove white space after tag up to the next non-whitespace character
"{tag--} \n\n\t text" -> "{tag}text"
"{tag--} text \n\n\t text" -> "{tag}text \n\n\t text"
{tag+-}
{tag-+} replace white space after tag up to the next non-whitespace character by a single line-break
"{tag-+} \n\n\t text" -> "{tag}\n\ntext"
"{tag-+} text \n\n\t text" -> "{tag}\n\ntext \n\n\t text"
{tag+} replace white space after tag up to the end of the line with an additional line-break
"{tag+} \n\t text" -> "{tag}\n\n\t text"
"{tag+} text \n\n\t text" -> "{tag}\n\ntext \n\n\t text"
Any combination of the above, say {--tag+} is possible. Any + modifiers are executed before - modifiers, so
"{tag+-}{--tag}" will lead to "{tag}{tag}"
NOTE: {tag+} and {tag-+} cause two trailing \n. This is done because PHP itself throws away the first \n.
So \n\n in the template will lead to \n in the output
*/
function smarty_prefilter_whitespace_control($string, $template) {
// $ldelim = $template->smarty->left_delimiter;
// $rdelim = $template->smarty->right_delimiter;
$ldelim = '{';
$rdelim = '}';
$_ldelim = preg_quote($ldelim);
$_rdelim = preg_quote($rdelim);
// remove preceeding whitepsace preserving a single line-break
$string = preg_replace('#\s*'. $_ldelim .'(?:-\+|\+-)#', "\n" . $ldelim, $string);
// remove trailing whitespace preserving s single line-break
$string = preg_replace('#(?:\+-|-\+)'. $_rdelim .'\s*#', $rdelim . "\n\n", $string);
// remove preceeding whitepsace
$string = preg_replace('#\s*'. $_ldelim .'--|[^\S\r\n]*'. $_ldelim .'-#', $ldelim, $string);
// remove trailing whitespace
$string = preg_replace('#--'. $_rdelim .'\s*|-'. $_rdelim .'[^\S\r\n]*#', $rdelim, $string);
// force trailing line-break
$string = preg_replace('#\+'. $_rdelim .'(?:\s*[\r\n]|[^\S\r\n]*)#', $rdelim . "\n\n", $string);
return $string;
}
echo smarty_prefilter_whitespace_control($string, null), "#end\n";
$tests = array(
"text \n\n\t {-tag}" => "text \n\n{tag}",
"text \n\n\t text\t {-tag}" => "text \n\n\t text{tag}",
"text \n\n\t {--tag}" => "text{tag}",
"text \n\n\t text\t {--tag}" => "text \n\n\t text{tag}",
"text \n\n\t {-+tag}" => "text\n{tag}",
"text \n\n\t text\t {-+tag}" => "text \n\n\t text\n{tag}",
"{tag-} \n\n\t text" => "{tag}\n\n\t text",
"{tag-} text \n\n\t text" => "{tag}text \n\n\t text",
"{tag--} \n\n\t text" => "{tag}text",
"{tag--} text \n\n\t text" => "{tag}text \n\n\t text",
"{tag-+} \n\n\t text" => "{tag}\n\ntext",
"{tag-+} text \n\n\t text" => "{tag}\n\ntext \n\n\t text",
"{tag+} \n\t text" => "{tag}\n\n\t text",
"{tag+} text \n\n\t text" => "{tag}\n\ntext \n\n\t text",
"{tag+-}{--tag}" => "{tag}{tag}",
);
function nl($string) {
$string = str_replace("\n", '\n', $string);
$string = str_replace("\t", '\t', $string);
return $string;
}
foreach ($tests as $in => $out) {
$res = smarty_prefilter_whitespace_control($in, null);
if ($res !== $out) {
echo "failed '", nl($in), "' got '", nl($res), "' but expected '", nl($out), "'\n";
}
}
echo "\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment