Skip to content

Commit c9acca6

Browse files
committed
Add an attr function to make outputting HTML attributes easier
1 parent b93eb3c commit c9acca6

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

extra/html-extra/HtmlExtension.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Twig\Extra\Html;
1313

1414
use Symfony\Component\Mime\MimeTypes;
15+
use Twig\Environment;
1516
use Twig\Error\RuntimeError;
1617
use Twig\Extension\AbstractExtension;
1718
use Twig\TwigFilter;
@@ -30,6 +31,7 @@ public function getFilters(): array
3031
{
3132
return [
3233
new TwigFilter('data_uri', [$this, 'dataUri']),
34+
new TwigFilter('html_attr_merge', 'twig_html_attr_merge'),
3335
];
3436
}
3537

@@ -38,6 +40,7 @@ public function getFunctions(): array
3840
return [
3941
new TwigFunction('html_classes', [self::class, 'htmlClasses']),
4042
new TwigFunction('html_cva', [self::class, 'htmlCva']),
43+
new TwigFunction('html_attr', 'twig_html_attr', ['needs_environment' => true, 'is_safe' => ['html']]),
4144
];
4245
}
4346

@@ -124,4 +127,75 @@ public static function htmlCva(array|string $base = [], array $variants = [], ar
124127
{
125128
return new Cva($base, $variants, $compoundVariants, $defaultVariant);
126129
}
130+
131+
static function twig_html_attr_merge(...$arrays): array
132+
{
133+
$result = [];
134+
135+
foreach ($arrays as $argNumber => $array) {
136+
if (!$array) {
137+
continue;
138+
}
139+
140+
if (!twig_test_iterable($array)) {
141+
throw new RuntimeError(sprintf('The "attr_merge" filter only works with arrays or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1));
142+
}
143+
144+
$array = twig_to_array($array);
145+
146+
foreach (['class', 'style', 'data'] as $deepMergeKey) {
147+
if (isset($array[$deepMergeKey])) {
148+
$value = $array[$deepMergeKey];
149+
unset($array[$deepMergeKey]);
150+
151+
if (!twig_test_iterable($value)) {
152+
$value = (array) $value;
153+
}
154+
155+
$value = twig_to_array($value);
156+
157+
$result[$deepMergeKey] = array_merge($result[$deepMergeKey] ?? [], $value);
158+
}
159+
}
160+
161+
$result = array_merge($result, $array);
162+
}
163+
164+
return $result;
165+
}
166+
167+
static function twig_html_attr(Environment $env, ...$args): string
168+
{
169+
$attr = twig_html_attr_merge(...$args);
170+
171+
if (isset($attr['class'])) {
172+
$attr['class'] = trim(implode(' ', array_values($attr['class'])));
173+
}
174+
175+
if (isset($attr['style'])) {
176+
$style = '';
177+
foreach ($attr['style'] as $name => $value) {
178+
if (is_numeric($name)) {
179+
$style .= $value.'; ';
180+
} else {
181+
$style .= $name.': '.$value.'; ';
182+
}
183+
}
184+
$attr['style'] = trim($style);
185+
}
186+
187+
if (isset($attr['data'])) {
188+
foreach ($attr['data'] as $name => $value) {
189+
$attr['data-'.$name] = $value;
190+
}
191+
unset($attr['data']);
192+
}
193+
194+
$result = '';
195+
foreach ($attr as $name => $value) {
196+
$result .= twig_escape_filter($env, $name, 'html_attr').'="'.htmlspecialchars($value).'" ';
197+
}
198+
199+
return trim($result);
200+
}
127201
}

0 commit comments

Comments
 (0)