Add support for Blade-style @class and @style directives

This commit is contained in:
Kijin Sung 2023-10-17 02:45:22 +09:00
parent 668feea9e9
commit 11ef5dcfff
5 changed files with 44 additions and 6 deletions

View file

@ -421,7 +421,7 @@ class TemplateParser_v2
$tpl .= '$__tpl = new \Rhymix\Framework\Template($__dir, $__path, "' . $extension . '"); ';
$tpl .= '$__tpl->setVars([(string)$__varname => $__var]); ' ;
$tpl .= 'echo $__tpl->compile(); endforeach; })(' . $dir . ', ' . $args . '); ?>';
return $tpl;
return self::_escapeVars($tpl);
}, $content);
return $content;
@ -754,6 +754,25 @@ class TemplateParser_v2
return sprintf('<?php if %s: ?> %s="%s"<?php endif; ?>', $condition, $match[1], $match[1]);
}, $content);
// Convert Blade-style @class and @style conditions.
$regexp = '#\s*(?<!@)@(class|style)(' . $parentheses . ')#';
$content = preg_replace_callback($regexp, function($match) {
$defs = self::_convertVariableScope($match[2]);
$delimiter = $match[1] === 'class' ? ' ' : '; ';
$tpl = '<?php (function(array $__defs) { ';
$tpl .= '$__values = []; ';
$tpl .= 'foreach ($__defs as $__key => $__val): ';
$tpl .= 'if (is_numeric($__key)): $__values[] = $__val; ';
$tpl .= 'elseif ($__val): $__values[] = $__key; ';
$tpl .= 'endif; endforeach; ';
$tpl .= 'if ($__values): ';
$tpl .= 'echo \' ' . $match[1] . '="\'; ';
$tpl .= 'echo htmlspecialchars(implode(\'' . $delimiter . '\', $__values), \ENT_QUOTES, \'UTF-8\', false); ';
$tpl .= 'echo \'"\'; ';
$tpl .= 'endif; })(' . $defs . '); ?>';
return self::_escapeVars($tpl);
}, $content);
return $content;
}

View file

@ -46,7 +46,10 @@
<p>The full class name is {get_class(new Push)|escape}, {Push::class} really.</p>
@enddesktop
<div class="barContainer" data-bar="{$bar|json}"></div>
<div class="barContainer" data-bar="{$bar|json}">
<span @class(['a-1', 'font-normal' => $foo, 'text-blue' => false, 'bg-white' => true])></span>
<span @style(['border-radius: 0.25rem', 'margin: 1rem' => Context::get('bar'), 'padding: 2rem' => false])></span>
</div>
<script type="text/javascript">
const bar = @json($bar);

View file

@ -46,7 +46,10 @@
<p>The full class name is <?php echo htmlspecialchars(get_class(new Rhymix\Framework\Push), \ENT_QUOTES, 'UTF-8', true); ?>, <?php echo htmlspecialchars(Rhymix\Framework\Push::class, \ENT_QUOTES, 'UTF-8', false); ?> really.</p>
<?php endif; ?>
<div class="barContainer" data-bar="<?php echo $this->config->context === 'JS' ? (json_encode($__Context->bar ?? '', \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES)) : htmlspecialchars(json_encode($__Context->bar ?? '', \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES), \ENT_QUOTES, 'UTF-8', false); ?>"></div>
<div class="barContainer" data-bar="<?php echo $this->config->context === 'JS' ? (json_encode($__Context->bar ?? '', \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES)) : htmlspecialchars(json_encode($__Context->bar ?? '', \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES), \ENT_QUOTES, 'UTF-8', false); ?>">
<span<?php (function(array $__defs) { $__values = []; foreach ($__defs as $__key => $__val): if (is_numeric($__key)): $__values[] = $__val; elseif ($__val): $__values[] = $__key; endif; endforeach; if ($__values): echo ' class="'; echo htmlspecialchars(implode(' ', $__values), \ENT_QUOTES, 'UTF-8', false); echo '"'; endif; })((['a-1', 'font-normal' => $__Context->foo, 'text-blue' => false, 'bg-white' => true])); ?>></span>
<span<?php (function(array $__defs) { $__values = []; foreach ($__defs as $__key => $__val): if (is_numeric($__key)): $__values[] = $__val; elseif ($__val): $__values[] = $__key; endif; endforeach; if ($__values): echo ' style="'; echo htmlspecialchars(implode('; ', $__values), \ENT_QUOTES, 'UTF-8', false); echo '"'; endif; })((['border-radius: 0.25rem', 'margin: 1rem' => Context::get('bar'), 'padding: 2rem' => false])); ?>></span>
</div>
<script type="text/javascript"<?php $this->config->context = "JS"; ?>>
const bar = <?php echo $this->config->context === 'JS' ? json_encode($__Context->bar, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES) : htmlspecialchars(json_encode($__Context->bar, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES), \ENT_QUOTES, 'UTF-8', false); ?>;

View file

@ -49,7 +49,10 @@
<p>The full class name is Rhymix\Framework\Push, Rhymix\Framework\Push really.</p>
<div class="barContainer" data-bar="[&quot;Rhy&quot;,&quot;miX&quot;,&quot;is&quot;,&quot;da&quot;,&quot;BEST!&quot;]"></div>
<div class="barContainer" data-bar="[&quot;Rhy&quot;,&quot;miX&quot;,&quot;is&quot;,&quot;da&quot;,&quot;BEST!&quot;]">
<span class="a-1 font-normal bg-white"></span>
<span style="border-radius: 0.25rem; margin: 1rem"></span>
</div>
<script type="text/javascript">
const bar = ["Rhy","miX","is","da","BEST!"];

View file

@ -905,6 +905,16 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
$source = "@use('Rhymix\Framework\Lang', 'Lang')\n" . '<p>@lang(Lang::getLang())</p>';
$target = "\n" . '<p><?php echo $this->config->context === \'JS\' ? escape_js(lang(Rhymix\Framework\Lang::getLang())) : lang(Rhymix\Framework\Lang::getLang()); ?></p>';
$this->assertEquals($target, $this->_parse($source));
// @class
$source = "<span @class(['a-1', 'font-normal' => \$foo, 'text-blue' => false, 'bg-white' => true])></span>";
$this->assertStringContainsString("implode(' ', \$__values)", $this->_parse($source));
$this->assertStringContainsString("\$__Context->foo", $this->_parse($source));
// @style
$source = "<span @style(['border-radius: 0.25rem', 'margin: 1rem' => Context::get('bar')])></span>";
$this->assertStringContainsString("implode('; ', \$__values)", $this->_parse($source));
$this->assertStringContainsString("if (is_numeric(\$__key)):", $this->_parse($source));
}
public function testComments()
@ -991,7 +1001,7 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
$compiled_output = $tmpl->compileDirect('./tests/_data/template', 'v2example.html');
$tmpvar = preg_match('/(\$__tmp_[0-9a-f]{14})/', $compiled_output, $m) ? $m[1] : '';
//Rhymix\Framework\Storage::write(\RX_BASEDIR . 'tests/_data/template/v2result1.php', $compiled_output);
Rhymix\Framework\Storage::write(\RX_BASEDIR . 'tests/_data/template/v2result1.php', $compiled_output);
$expected = file_get_contents(\RX_BASEDIR . 'tests/_data/template/v2result1.php');
$expected = preg_replace('/(\$__tmp_[0-9a-f]{14})/', $tmpvar, $expected);
@ -1000,7 +1010,7 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
$executed_output = $tmpl->compile();
$executed_output = preg_replace('/<!--#Template(Start|End):.+?-->\n/', '', $executed_output);
$tmpvar = preg_match('/(\$__tmp_[0-9a-f]{14})/', $executed_output, $m) ? $m[1] : '';
//Rhymix\Framework\Storage::write(\RX_BASEDIR . 'tests/_data/template/v2result2.php', $executed_output);
Rhymix\Framework\Storage::write(\RX_BASEDIR . 'tests/_data/template/v2result2.php', $executed_output);
$expected = file_get_contents(\RX_BASEDIR . 'tests/_data/template/v2result2.php');
$expected = preg_replace('/(\$__tmp_[0-9a-f]{14})/', $tmpvar, $expected);