-
-
Notifications
You must be signed in to change notification settings - Fork 84
Introduce stimulus_controller to ease Stimulus Values API usage #109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony WebpackEncoreBundle package. | ||
* (c) Fabien Potencier <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\WebpackEncoreBundle\Twig; | ||
|
||
use Twig\Environment; | ||
use Twig\Extension\AbstractExtension; | ||
use Twig\TwigFunction; | ||
|
||
final class StimulusTwigExtension extends AbstractExtension | ||
{ | ||
public function getFunctions() | ||
{ | ||
return [ | ||
new TwigFunction('stimulus_controller', [$this, 'renderStimulusController'], ['needs_environment' => true, 'is_safe' => ['all']]), | ||
]; | ||
} | ||
|
||
public function renderStimulusController(Environment $env, array $data): string | ||
{ | ||
if (!$data) { | ||
return ''; | ||
} | ||
|
||
$controllers = []; | ||
$values = []; | ||
|
||
foreach ($data as $controllerName => $controllerValues) { | ||
$controllerName = twig_escape_filter($env, $this->normalizeControllerName($controllerName), 'html_attr'); | ||
$controllers[] = $controllerName; | ||
|
||
foreach ($controllerValues as $key => $value) { | ||
if (!is_scalar($value)) { | ||
nicolas-grekas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
$value = json_encode($value); | ||
} | ||
|
||
$key = twig_escape_filter($env, $this->normalizeKeyName($key), 'html_attr'); | ||
$value = twig_escape_filter($env, $value, 'html_attr'); | ||
|
||
$values[] = 'data-'.$controllerName.'-'.$key.'-value="'.$value.'"'; | ||
} | ||
} | ||
|
||
return rtrim('data-controller="'.implode(' ', $controllers).'" '.implode(' ', $values)); | ||
nicolas-grekas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/** | ||
* Normalize a Stimulus controller name into its HTML equivalent (no special character and / becomes --). | ||
* | ||
* @see https://stimulus.hotwire.dev/reference/controllers | ||
*/ | ||
private function normalizeControllerName(string $str): string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this belongs here. It seems to me that the UX packages should be responsible for calling this function with their already-normalized name. I'd almost rather throw an exception if something invalid is passed (but probably, just do nothing). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea was to allow users to pass the same value they have in their controller.json file: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, that's a really good point. I'd like to keep it then for DX. |
||
{ | ||
return preg_replace('/^@/', '', str_replace('_', '-', str_replace('/', '--', $str))); | ||
} | ||
|
||
/** | ||
* Normalize a Stimulus Value API key into its HTML equivalent ("kebab case"). | ||
* Backport features from symfony/string. | ||
* | ||
* @see https://stimulus.hotwire.dev/reference/values | ||
*/ | ||
private function normalizeKeyName(string $str): string | ||
{ | ||
// Adapted from ByteString::camel | ||
$str = ucfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $str)))); | ||
|
||
// Adapted from ByteString::snake | ||
return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1-\2', $str)); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.