Just stubled over this old thread and want to share my approach.
As I’m using Alpine a lot, I need to be able to inject other attributes like @click
or :class
.
(In addition I replace stroke and fill color values to currentColor
– but that’s quite experimental. Just using it for now and see how it works for me. Makes the SVG sync to text-color without further configuration)
This is how it’s used in a template / snippet (semi-nonsense example):
<a class="text-blue-200 hover:text-red-400" x-data="{count: 0}" @click="count++">
Link
<?= svge('assets/arrow.svg', ['class' => 'w-20 duration-150', ':class' => "{'rotate-90': count > 3}"]) ?>
</a>
// e.g. in plugins/my-plugin/index.php
function svge(string $filepath, array $attrs = [])
{
// get svg content
if (!$content = svg($filepath)) {
throw new Exception("SVG filepath not found: $filepath");
}
// replace fill / stroke
$content = preg_replace_callback(
'/(fill|stroke)="([^"]*)"/i',
function ($matches) {
$attribute = $matches[1];
$value = strtolower($matches[2]);
if ($value !== 'none' && $value !== 'transparent') {
return "$attribute=\"currentColor\"";
}
return $matches[0];
},
$content
);
// extand <svg> tag
// TODO: handle extending existing attributes
foreach ($attrs as $attr => $value) {
$content = Str::replace(
$content,
'<svg',
Str::template('<svg {{ attr }}', ['attr' => Html::attr($attr, $value)])
);
}
return $content;
}