From 3a282ecbe42a16693cf5d365b44ff25f4cf4b746 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 10 Apr 2024 10:23:52 -0400 Subject: [PATCH 1/3] wip --- src/Tags/Concerns/RendersAttributes.php | 12 ++++--- tests/Tags/Concerns/RendersAttributesTest.php | 34 +++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/Tags/Concerns/RendersAttributes.php b/src/Tags/Concerns/RendersAttributes.php index 5953ed570e..48de5ff275 100644 --- a/src/Tags/Concerns/RendersAttributes.php +++ b/src/Tags/Concerns/RendersAttributes.php @@ -37,19 +37,23 @@ protected function renderAttributes($attributes) /** * Render HTML attributes from tag params. * - * Parameters that are not prefixed with attr: will be automatically removed. + * Parameters that are not approved will be filtered out. * * @return string */ protected function renderAttributesFromParams() { - $params = $this->params->filter(function ($value, $attribute) { - return preg_match('/^attr:/', $attribute); - })->all(); + $params = $this->params->filter(fn ($v, $attr) => $this->isAllowedParamAttr($attr))->all(); return $this->renderAttributes($params); } + private function isAllowedParamAttr($attribute): bool + { + return Str::startsWith($attribute, ['attr:', 'aria-', 'data-']) + || in_array($attribute, ['class', 'autocomplete']); + } + /** * Render HTML attributes and merge attributes from tag params. * diff --git a/tests/Tags/Concerns/RendersAttributesTest.php b/tests/Tags/Concerns/RendersAttributesTest.php index 5ccc24b7d4..5aa7244eca 100644 --- a/tests/Tags/Concerns/RendersAttributesTest.php +++ b/tests/Tags/Concerns/RendersAttributesTest.php @@ -24,12 +24,12 @@ public function it_renders_attributes_from_array() $this->assertEquals('', $this->tag->renderAttributes([])); $output = $this->tag->renderAttributes([ - 'attr:class' => 'm-0 mb-2', - 'attr::name' => 'first_name', - 'attr:disabled' => 'true', - 'attr:autocomplete' => true, - 'attr:focusable' => false, - 'attr:dont_render_nulls' => null, + 'class' => 'm-0 mb-2', + ':name' => 'first_name', + 'disabled' => 'true', + 'autocomplete' => true, + 'focusable' => false, + 'dont_render_nulls' => null, ]); $this->assertEquals('class="m-0 mb-2" :name="first_name" disabled="true" autocomplete="true" focusable="false"', $output); @@ -55,6 +55,28 @@ public function it_renders_attributes_from_params() $this->assertEquals('class="m-0 mb-2" name="Han" src="avatar.jpg" focusable="false" disabled="true" autocomplete="true"', $output); } + + /** @test */ + public function it_renders_certain_attributes_from_params_without_needing_attr_prefix() + { + $this->assertEquals('', $this->tag->renderAttributesFromParams()); + + $output = $this->tag + ->setContext(['first_name' => 'Han']) + ->setParameters([ + 'class' => 'm-0 mb-2', + 'autocomplete' => true, + 'aria-alfa' => 'bravo', + 'aria-charlie' => 'delta', + 'aria-echo' => null, + 'data-alfa' => 'bravo', + 'data-charlie' => 'delta', + 'data-echo' => null, + ]) + ->renderAttributesFromParams(); + + $this->assertEquals('class="m-0 mb-2" autocomplete="true" aria-alfa="bravo" aria-charlie="delta" data-alfa="bravo" data-charlie="delta"', $output); + } } class FakeTagWithRendersAttributes extends Tags From 398a2987d3ffe4a33162489329935154ab5199f6 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 10 Apr 2024 11:50:19 -0400 Subject: [PATCH 2/3] just revert to old behavior --- src/Tags/Concerns/RendersAttributes.php | 17 +++++------------ src/Tags/Concerns/RendersForms.php | 2 +- src/Tags/Svg.php | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Tags/Concerns/RendersAttributes.php b/src/Tags/Concerns/RendersAttributes.php index 48de5ff275..c5bb8a02db 100644 --- a/src/Tags/Concerns/RendersAttributes.php +++ b/src/Tags/Concerns/RendersAttributes.php @@ -37,33 +37,26 @@ protected function renderAttributes($attributes) /** * Render HTML attributes from tag params. * - * Parameters that are not approved will be filtered out. - * + * @param array $except Parameters that should be excluded. Typically used for tag parameters that control behavior. * @return string */ - protected function renderAttributesFromParams() + protected function renderAttributesFromParams(array $except = []) { - $params = $this->params->filter(fn ($v, $attr) => $this->isAllowedParamAttr($attr))->all(); + $params = $this->params->reject(fn ($v, $attr) => in_array($attr, $except))->all(); return $this->renderAttributes($params); } - private function isAllowedParamAttr($attribute): bool - { - return Str::startsWith($attribute, ['attr:', 'aria-', 'data-']) - || in_array($attribute, ['class', 'autocomplete']); - } - /** * Render HTML attributes and merge attributes from tag params. * * @return string */ - protected function renderAttributesFromParamsWith(array $attrs) + protected function renderAttributesFromParamsWith(array $attrs, array $except = []) { return collect([ $this->renderAttributes($attrs), - $this->renderAttributesFromParams(), + $this->renderAttributesFromParams($except), ])->filter()->implode(' '); } } diff --git a/src/Tags/Concerns/RendersForms.php b/src/Tags/Concerns/RendersForms.php index 2f74515451..a15f4ee9c6 100644 --- a/src/Tags/Concerns/RendersForms.php +++ b/src/Tags/Concerns/RendersForms.php @@ -70,7 +70,7 @@ protected function formOpen($action, $method = 'POST', $knownTagParams = [], $ad $attrs['enctype'] = 'multipart/form-data'; } - $attrs = $this->renderAttributesFromParamsWith($attrs); + $attrs = $this->renderAttributesFromParamsWith($attrs, except: $knownTagParams); $html = collect(['filter()->implode(' ').'>'; diff --git a/src/Tags/Svg.php b/src/Tags/Svg.php index 5f3c9775ff..eabcdf34c8 100644 --- a/src/Tags/Svg.php +++ b/src/Tags/Svg.php @@ -48,7 +48,7 @@ public function index() $svg = $this->params->get('src'); } - $attributes = $this->renderAttributesFromParams(); + $attributes = $this->renderAttributesFromParams(except: ['src', 'title', 'desc', 'sanitize']); if ($this->params->get('title') || $this->params->get('desc')) { $svg = $this->setTitleAndDesc($svg); From 6fc68d16fa005292282fc941d98b8f41363eb057 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 10 Apr 2024 11:57:12 -0400 Subject: [PATCH 3/3] basically revert pr 9576 --- src/Tags/Concerns/RendersForms.php | 5 +- tests/Fieldtypes/IconTest.php | 2 +- tests/Tags/Concerns/RendersAttributesTest.php | 52 ++++++++++++++----- tests/Tags/Concerns/RendersFormsTest.php | 2 +- tests/Tags/Form/FormCreateTest.php | 2 +- tests/Tags/SvgTagTest.php | 2 +- tests/Tags/User/ForgotPasswordFormTest.php | 2 +- tests/Tags/User/LoginFormTest.php | 2 +- tests/Tags/User/PasswordFormTest.php | 2 +- tests/Tags/User/ProfileFormTest.php | 2 +- tests/Tags/User/RegisterFormTest.php | 2 +- 11 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/Tags/Concerns/RendersForms.php b/src/Tags/Concerns/RendersForms.php index a15f4ee9c6..f80ba5c479 100644 --- a/src/Tags/Concerns/RendersForms.php +++ b/src/Tags/Concerns/RendersForms.php @@ -70,7 +70,10 @@ protected function formOpen($action, $method = 'POST', $knownTagParams = [], $ad $attrs['enctype'] = 'multipart/form-data'; } - $attrs = $this->renderAttributesFromParamsWith($attrs, except: $knownTagParams); + $attrs = $this->renderAttributesFromParamsWith( + $attrs, + except: array_merge(['method', 'action'], $knownTagParams) + ); $html = collect(['filter()->implode(' ').'>'; diff --git a/tests/Fieldtypes/IconTest.php b/tests/Fieldtypes/IconTest.php index 258fc40339..7500fdb0cb 100644 --- a/tests/Fieldtypes/IconTest.php +++ b/tests/Fieldtypes/IconTest.php @@ -21,7 +21,7 @@ public function it_finds_default_icons() /** @test */ public function it_accepts_svg_strings() { - $result = (string) Antlers::parse('{{ svg :src="test" attr:class="w-4 h-4" sanitize="false" }}', ['test' => new Value('add', $this->fieldtype())]); + $result = (string) Antlers::parse('{{ svg :src="test" class="w-4 h-4" sanitize="false" }}', ['test' => new Value('add', $this->fieldtype())]); $this->assertStringContainsString('tag ->setContext(['first_name' => 'Han']) ->setParameters([ - 'attr:class' => 'm-0 mb-2', - ':attr:name' => 'first_name', + 'class' => 'm-0 mb-2', + ':name' => 'first_name', 'attr:src' => 'avatar.jpg', - 'attr:focusable' => false, - 'attr:dont_render_nulls' => null, - 'attr:disabled' => 'true', - 'attr:autocomplete' => true, + 'focusable' => false, + 'dont_render_nulls' => null, + 'disabled' => 'true', + 'autocomplete' => true, ]) ->renderAttributesFromParams(); @@ -57,7 +57,31 @@ public function it_renders_attributes_from_params() } /** @test */ - public function it_renders_certain_attributes_from_params_without_needing_attr_prefix() + public function it_wont_render_attributes_for_known_params_unless_attr_prepended() + { + $output = $this->tag + ->setParameters([ + 'class' => 'm-0 mb-2', + 'src' => 'avatar.jpg', + 'name' => 'Han', + ]) + ->renderAttributesFromParams(except: ['src', 'name']); + + $this->assertEquals('class="m-0 mb-2"', $output); + + $output = $this->tag + ->setParameters([ + 'class' => 'm-0 mb-2', + 'attr:src' => 'avatar.jpg', + 'name' => 'Han', + ]) + ->renderAttributesFromParams(['src', 'name']); + + $this->assertEquals('class="m-0 mb-2" src="avatar.jpg"', $output); + } + + /** @test */ + public function it_will_render_falsy_attributes() { $this->assertEquals('', $this->tag->renderAttributesFromParams()); @@ -65,17 +89,17 @@ public function it_renders_certain_attributes_from_params_without_needing_attr_p ->setContext(['first_name' => 'Han']) ->setParameters([ 'class' => 'm-0 mb-2', + ':name' => 'first_name', + 'attr:src' => 'avatar.jpg', + 'focusable' => false, + 'dont_render_nulls' => null, + 'disabled' => 'true', 'autocomplete' => true, - 'aria-alfa' => 'bravo', - 'aria-charlie' => 'delta', - 'aria-echo' => null, - 'data-alfa' => 'bravo', - 'data-charlie' => 'delta', - 'data-echo' => null, + 'aria-hidden' => true, ]) ->renderAttributesFromParams(); - $this->assertEquals('class="m-0 mb-2" autocomplete="true" aria-alfa="bravo" aria-charlie="delta" data-alfa="bravo" data-charlie="delta"', $output); + $this->assertEquals('class="m-0 mb-2" name="Han" src="avatar.jpg" focusable="false" disabled="true" autocomplete="true" aria-hidden="true"', $output); } } diff --git a/tests/Tags/Concerns/RendersFormsTest.php b/tests/Tags/Concerns/RendersFormsTest.php index f84597ebd7..ceae4c5bf5 100644 --- a/tests/Tags/Concerns/RendersFormsTest.php +++ b/tests/Tags/Concerns/RendersFormsTest.php @@ -47,7 +47,7 @@ public function it_renders_form_open_tags_with_custom_attributes() { $output = $this->tag ->setParameters([ - 'attr:class' => 'mb-2', + 'class' => 'mb-2', 'attr:id' => 'form', 'method' => 'this should not render', 'action' => 'this should not render', diff --git a/tests/Tags/Form/FormCreateTest.php b/tests/Tags/Form/FormCreateTest.php index 805ad4d43c..d097f5d699 100644 --- a/tests/Tags/Form/FormCreateTest.php +++ b/tests/Tags/Form/FormCreateTest.php @@ -36,7 +36,7 @@ public function it_renders_form() /** @test */ public function it_renders_form_with_params() { - $output = $this->tag('{{ form:contact redirect="/submitted" error_redirect="/errors" attr:class="form" attr:id="form" }}{{ /form:contact }}'); + $output = $this->tag('{{ form:contact redirect="/submitted" error_redirect="/errors" class="form" id="form" }}{{ /form:contact }}'); $this->assertStringStartsWith('
', $output); $this->assertStringContainsString('', $output); diff --git a/tests/Tags/SvgTagTest.php b/tests/Tags/SvgTagTest.php index 40a8155da0..d2c82f12b1 100644 --- a/tests/Tags/SvgTagTest.php +++ b/tests/Tags/SvgTagTest.php @@ -30,7 +30,7 @@ public function it_renders_svg() /** @test */ public function it_renders_svg_with_additional_params() { - $this->assertStringStartsWith('assertStringStartsWith('tag('{{ user:forgot_password_form redirect="/submitted" error_redirect="/errors" reset_url="/resetting" attr:class="form" attr:id="form" }}{{ /user:forgot_password_form }}'); + $output = $this->tag('{{ user:forgot_password_form redirect="/submitted" error_redirect="/errors" reset_url="/resetting" class="form" id="form" }}{{ /user:forgot_password_form }}'); $this->assertStringStartsWith('
', $output); $this->assertStringContainsString('', $output); diff --git a/tests/Tags/User/LoginFormTest.php b/tests/Tags/User/LoginFormTest.php index 75fc7c8df4..0f6c069508 100644 --- a/tests/Tags/User/LoginFormTest.php +++ b/tests/Tags/User/LoginFormTest.php @@ -30,7 +30,7 @@ public function it_renders_form() /** @test */ public function it_renders_form_with_params() { - $output = $this->tag('{{ user:login_form redirect="/submitted" error_redirect="/errors" attr:class="form" attr:id="form" }}{{ /user:login_form }}'); + $output = $this->tag('{{ user:login_form redirect="/submitted" error_redirect="/errors" class="form" id="form" }}{{ /user:login_form }}'); $this->assertStringStartsWith('
', $output); $this->assertStringContainsString('', $output); diff --git a/tests/Tags/User/PasswordFormTest.php b/tests/Tags/User/PasswordFormTest.php index 495b757b4e..f7383cd71d 100644 --- a/tests/Tags/User/PasswordFormTest.php +++ b/tests/Tags/User/PasswordFormTest.php @@ -34,7 +34,7 @@ public function it_renders_form_with_params() { $this->actingAs(User::make()->password('mypassword')->save()); - $output = $this->tag('{{ user:password_form redirect="/submitted" error_redirect="/errors" attr:class="form" attr:id="form" }}{{ /user:password_form }}'); + $output = $this->tag('{{ user:password_form redirect="/submitted" error_redirect="/errors" class="form" id="form" }}{{ /user:password_form }}'); $this->assertStringStartsWith('
', $output); $this->assertStringContainsString('', $output); diff --git a/tests/Tags/User/ProfileFormTest.php b/tests/Tags/User/ProfileFormTest.php index 450213814b..6abfc404c7 100644 --- a/tests/Tags/User/ProfileFormTest.php +++ b/tests/Tags/User/ProfileFormTest.php @@ -35,7 +35,7 @@ public function it_renders_form_with_params() { $this->actingAs(User::make()->save()); - $output = $this->tag('{{ user:profile_form redirect="/submitted" error_redirect="/errors" attr:class="form" attr:id="form" }}{{ /user:profile_form }}'); + $output = $this->tag('{{ user:profile_form redirect="/submitted" error_redirect="/errors" class="form" id="form" }}{{ /user:profile_form }}'); $this->assertStringStartsWith('
', $output); $this->assertStringContainsString('', $output); diff --git a/tests/Tags/User/RegisterFormTest.php b/tests/Tags/User/RegisterFormTest.php index 77c7d4df04..d83f5a7934 100644 --- a/tests/Tags/User/RegisterFormTest.php +++ b/tests/Tags/User/RegisterFormTest.php @@ -36,7 +36,7 @@ public function it_renders_form() /** @test */ public function it_renders_form_with_params() { - $output = $this->tag('{{ user:register_form redirect="/submitted" error_redirect="/errors" attr:class="form" attr:id="form" }}{{ /user:register_form }}'); + $output = $this->tag('{{ user:register_form redirect="/submitted" error_redirect="/errors" class="form" id="form" }}{{ /user:register_form }}'); $this->assertStringStartsWith('
', $output); $this->assertStringContainsString('', $output);