Skip to content

Commit

Permalink
Change: improve the implementation of spaceless
Browse files Browse the repository at this point in the history
  • Loading branch information
satrun77 committed Nov 1, 2021
1 parent 090df36 commit ee204d1
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 12 deletions.
4 changes: 4 additions & 0 deletions _config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ SilverStripe\Core\Injector\Injector:
spaceless: ['\Moo\Template\Parser\Spaceless', 'spaceless']
openBlocks:
content: ['\Moo\Template\Parser\TemplateBlock', 'content']

SilverStripe\ORM\FieldType\DBString:
extensions:
- Moo\Template\Extension\SpacelessCast
29 changes: 29 additions & 0 deletions src/Template/Extension/SpacelessCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Moo\Template\Extension;

use Moo\Template\Parser\Spaceless;
use SilverStripe\Core\Extension;
use SilverStripe\ORM\FieldType\DBField;

class SpacelessCast extends Extension
{
private static array $casting = [
'Spaceless' => 'HTMLText',
];

/**
* Get string without extra spaces.
*/
public function Spaceless(): DBField
{
return DBField::create_field(
'HTMLText',
Spaceless::spaceless([
'Template' => [
'php' => $this->getOwner()->RAW(),
],
])
);
}
}
120 changes: 108 additions & 12 deletions src/Template/Parser/Spaceless.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,124 @@
*/
class Spaceless
{
/**
* Remove space from the start of the statement.
*/
protected static array $patternStart = [
'/\'(\s+)([^\s\'])/m',
"'$2",
];

/**
* Remove space from between HTML tags.
*/
protected static array $patternBetweenTag = [
'/>\s+</',
'><',
];

/**
* Remove space from the end of the statement.
*/
protected static array $patternEnd = [
'/([^\s\'])(\s+)\';/m',
"$1';",
];

/**
* Convert multiple spaces into one space.
*/
protected static array $patternOneSpace = [
'!\s+!',
' ',
];

/**
* Remove space from empty statement `$val .= ' ';`.
*/
protected static array $patternEmpty = [
'/\'(\s+)\';/m',
"'';",
];

/**
* Remove white spaces from around template code.
*
* @param $res
* @return null|string|string[]
* @param array $res
*
* @return ?string
*/
public static function spaceless($res)
{
// Pattern to find whitespaces
// Template string code to remove whitespaces from
$php = $res['Template']['php'];

// Convert into an array
$code = static::toStatementPerLine($php);

// Clean up each i tem in the array
$index = 0;
foreach ($code as $key => $line) {
$code[$key] = static::cleanCode((string) $line, $index);
++$index;
}

return implode("\n", $code);
}

/**
* Clean up a line of code based on its position `$index`.
*/
protected static function cleanCode(string $value, int $index): string
{
// Default replacements
$pattern = [
'/\'(\s+)([^\s\'])/m',
'/\'(\s+)\'/m',
'/([^\s\'])(\s+)\';/m',
'/>\s+</',
static::$patternEnd[0],
static::$patternOneSpace[0],
static::$patternEmpty[0],
static::$patternBetweenTag[0],
];

// Template string code to remove whitespaces from
$php = $res['Template']['php'];
$replacement = [
static::$patternEnd[1],
static::$patternOneSpace[1],
static::$patternEmpty[1],
static::$patternBetweenTag[1],
];

// Replacements for first line of code
if ($index === 0) {
$pattern = [
static::$patternStart[0],
static::$patternEnd[0],
static::$patternOneSpace[0],
static::$patternEmpty[0],
static::$patternBetweenTag[0],
];

// Remove whitespaces
$php = preg_replace($pattern, ["'$2", "''", "$1';", '><'], $php);
$replacement = [
static::$patternStart[1],
static::$patternEnd[1],
static::$patternOneSpace[1],
static::$patternEmpty[1],
static::$patternBetweenTag[1],
];
}

return preg_replace($pattern, $replacement, $value);
}

/**
* Convert the PHP string into an array of items. One statement per line.
*/
protected static function toStatementPerLine(string $value): array
{
// Convert string into single line string
$value = str_replace(["\r\n", "\n", "\r", "\t"], '', $value);
// Add break-line before every start of a statement `$val .=`
$value = str_replace('$val .=', "\n\$val .=", $value);

return $php;
// Convert the string into an array item per line
return array_filter(explode("\n", $value));
}
}

0 comments on commit ee204d1

Please sign in to comment.