From f93f53d55ce11d967228fa764ef700856843d87e Mon Sep 17 00:00:00 2001 From: mscherer Date: Thu, 19 Feb 2026 16:29:49 +0100 Subject: [PATCH] Allow icon() to work with empty namespace and/or prefix Icon sets like Remixicon don't use a namespace class. Setting namespace to null or empty string previously resulted in extra spaces in the generated class attribute. This change makes both namespace and prefix optional: - Null/empty namespace is now properly omitted - Null/empty prefix uses just the icon name without a prefix Fixes #429 --- src/View/Helper/HtmlHelper.php | 16 ++++- tests/TestCase/View/Helper/HtmlHelperTest.php | 62 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/View/Helper/HtmlHelper.php b/src/View/Helper/HtmlHelper.php index 9449bbec..f5626010 100644 --- a/src/View/Helper/HtmlHelper.php +++ b/src/View/Helper/HtmlHelper.php @@ -91,10 +91,20 @@ public function icon(string $name, array $options = []): string 'class' => null, ]; - $classes = [$options['namespace'], $options['prefix'] . '-' . $name]; - if (!empty($options['size'])) { - $classes[] = $options['prefix'] . '-' . $options['size']; + $classes = []; + if ($options['namespace']) { + $classes[] = $options['namespace']; } + + if ($options['prefix']) { + $classes[] = $options['prefix'] . '-' . $name; + if (!empty($options['size'])) { + $classes[] = $options['prefix'] . '-' . $options['size']; + } + } else { + $classes[] = $name; + } + $options = $this->injectClasses($classes, $options); return $this->formatTemplate('tag', [ diff --git a/tests/TestCase/View/Helper/HtmlHelperTest.php b/tests/TestCase/View/Helper/HtmlHelperTest.php index 1df3e320..86e31cb4 100644 --- a/tests/TestCase/View/Helper/HtmlHelperTest.php +++ b/tests/TestCase/View/Helper/HtmlHelperTest.php @@ -75,4 +75,66 @@ public function testIcon() ]; $this->assertHtml($expected, $result); } + + public function testIconWithoutNamespace(): void + { + // Remixicon style: ri-home-line (no namespace, just prefix) + $result = $this->Html->icon('home-line', ['namespace' => null, 'prefix' => 'ri']); + $expected = [ + 'i' => ['class' => 'ri-home-line'], + '/i', + ]; + $this->assertHtml($expected, $result); + + // With empty string namespace + $result = $this->Html->icon('home-line', ['namespace' => '', 'prefix' => 'ri']); + $expected = [ + 'i' => ['class' => 'ri-home-line'], + '/i', + ]; + $this->assertHtml($expected, $result); + + // With size + $result = $this->Html->icon('home-line', ['namespace' => null, 'prefix' => 'ri', 'size' => 'lg']); + $expected = [ + 'i' => ['class' => 'ri-home-line ri-lg'], + '/i', + ]; + $this->assertHtml($expected, $result); + } + + public function testIconWithoutPrefix(): void + { + // Icon set with namespace but no prefix + $result = $this->Html->icon('home', ['namespace' => 'icons', 'prefix' => null]); + $expected = [ + 'i' => ['class' => 'icons home'], + '/i', + ]; + $this->assertHtml($expected, $result); + } + + public function testIconWithoutNamespaceAndPrefix(): void + { + // Hypothetical icon set using custom tag and just the icon name + $result = $this->Html->icon('home', ['tag' => 'icon', 'namespace' => null, 'prefix' => null]); + $expected = [ + 'icon' => ['class' => 'home'], + '/icon', + ]; + $this->assertHtml($expected, $result); + + // With additional class + $result = $this->Html->icon('home', [ + 'tag' => 'icon', + 'namespace' => null, + 'prefix' => null, + 'class' => 'fs-5', + ]); + $expected = [ + 'icon' => ['class' => 'fs-5 home'], + '/icon', + ]; + $this->assertHtml($expected, $result); + } }