Skip to content

Commit

Permalink
Add an attr function to make outputting HTML attributes easier
Browse files Browse the repository at this point in the history
  • Loading branch information
mpdude committed Sep 30, 2024
1 parent b93eb3c commit 03a5de1
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions extra/html-extra/HtmlExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
namespace Twig\Extra\Html;

use Symfony\Component\Mime\MimeTypes;
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Extension\AbstractExtension;
use Twig\Extension\CoreExtension;
use Twig\Extension\EscaperExtension;
use Twig\Runtime\EscaperRuntime;
use Twig\TwigFilter;
use Twig\TwigFunction;

Expand All @@ -30,6 +34,7 @@ public function getFilters(): array
{
return [
new TwigFilter('data_uri', [$this, 'dataUri']),
new TwigFilter('html_attr_merge', [self::class, 'htmlAttrMerge']),
];
}

Expand All @@ -38,6 +43,7 @@ public function getFunctions(): array
return [
new TwigFunction('html_classes', [self::class, 'htmlClasses']),
new TwigFunction('html_cva', [self::class, 'htmlCva']),
new TwigFunction('html_attr', [self::class, 'htmlAttr'], ['needs_environment' => true, 'is_safe' => ['html']]),
];
}

Expand Down Expand Up @@ -124,4 +130,77 @@ public static function htmlCva(array|string $base = [], array $variants = [], ar
{
return new Cva($base, $variants, $compoundVariants, $defaultVariant);
}

public static function htmlAttrMerge(...$arrays): array
{
$result = [];

foreach ($arrays as $argNumber => $array) {
if (!$array) {
continue;
}

if (!is_iterable($array)) {
throw new RuntimeError(sprintf('The "attr_merge" filter only works with arrays or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1));
}

$array = CoreExtension::toArray($array);

foreach (['class', 'style', 'data', 'aria'] as $deepMergeKey) {
if (isset($array[$deepMergeKey])) {
$value = $array[$deepMergeKey];
unset($array[$deepMergeKey]);

if (!is_iterable($value)) {
$value = (array) $value;
}

$value = CoreExtension::toArray($value);

$result[$deepMergeKey] = array_merge($result[$deepMergeKey] ?? [], $value);
}
}

$result = array_merge($result, $array);
}

return $result;
}

public static function htmlAttr(Environment $env, ...$args): string
{
$attr = self::htmlAttrMerge(...$args);

if (isset($attr['class'])) {
$attr['class'] = trim(implode(' ', $attr['class']));
}

if (isset($attr['style'])) {
$style = '';
foreach ($attr['style'] as $name => $value) {
if (is_numeric($name)) {
$style .= $value.'; ';
} else {
$style .= $name.': '.$value.'; ';
}
}
$attr['style'] = trim($style);
}

if (isset($attr['data'])) {
foreach ($attr['data'] as $name => $value) {
$attr['data-'.$name] = $value;
}
unset($attr['data']);
}

$result = '';
$runtime = $env->getRuntime(EscaperRuntime::class);

foreach ($attr as $name => $value) {
$result .= $runtime->escape($name, 'html_attr').'="'.$runtime->escape($value).'" ';
}

return trim($result);
}
}

0 comments on commit 03a5de1

Please sign in to comment.