From bd7fe2a6070d91e5f336755daaa3ead84025a6d7 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Tue, 18 Nov 2025 17:19:43 -0800 Subject: [PATCH 1/2] Don't pass a block to input elements --- lib/superform/rails/components/input.rb | 2 +- lib/superform/rails/field.rb | 68 +++++++++---------- .../rails/components/input_component_spec.rb | 17 ++++- .../rails/field_convenience_methods_spec.rb | 49 ++++++++++++- 4 files changed, 99 insertions(+), 37 deletions(-) diff --git a/lib/superform/rails/components/input.rb b/lib/superform/rails/components/input.rb index 02e40b4..67875d7 100644 --- a/lib/superform/rails/components/input.rb +++ b/lib/superform/rails/components/input.rb @@ -2,7 +2,7 @@ module Superform module Rails module Components class Input < Field - def view_template(&) + def view_template input(**attributes) end diff --git a/lib/superform/rails/field.rb b/lib/superform/rails/field.rb index f82325f..f2453bc 100644 --- a/lib/superform/rails/field.rb +++ b/lib/superform/rails/field.rb @@ -72,73 +72,73 @@ def human_attribute_name # field(:birthday).date # field(:secret).hidden(value: "token123") # field(:gender).radio("male", id: "user_gender_male") - def text(*, **, &) - input(*, **, type: :text, &) + def text(*, **) + input(*, **, type: :text) end - def hidden(*, **, &) - input(*, **, type: :hidden, &) + def hidden(*, **) + input(*, **, type: :hidden) end - def password(*, **, &) - input(*, **, type: :password, &) + def password(*, **) + input(*, **, type: :password) end - def email(*, **, &) - input(*, **, type: :email, &) + def email(*, **) + input(*, **, type: :email) end - def url(*, **, &) - input(*, **, type: :url, &) + def url(*, **) + input(*, **, type: :url) end - def tel(*, **, &) - input(*, **, type: :tel, &) + def tel(*, **) + input(*, **, type: :tel) end alias_method :phone, :tel - def number(*, **, &) - input(*, **, type: :number, &) + def number(*, **) + input(*, **, type: :number) end - def range(*, **, &) - input(*, **, type: :range, &) + def range(*, **) + input(*, **, type: :range) end - def date(*, **, &) - input(*, **, type: :date, &) + def date(*, **) + input(*, **, type: :date) end - def time(*, **, &) - input(*, **, type: :time, &) + def time(*, **) + input(*, **, type: :time) end - def datetime(*, **, &) - input(*, **, type: :"datetime-local", &) + def datetime(*, **) + input(*, **, type: :"datetime-local") end - def month(*, **, &) - input(*, **, type: :month, &) + def month(*, **) + input(*, **, type: :month) end - def week(*, **, &) - input(*, **, type: :week, &) + def week(*, **) + input(*, **, type: :week) end - def color(*, **, &) - input(*, **, type: :color, &) + def color(*, **) + input(*, **, type: :color) end - def search(*, **, &) - input(*, **, type: :search, &) + def search(*, **) + input(*, **, type: :search) end - def file(*, **, &) - input(*, **, type: :file, &) + def file(*, **) + input(*, **, type: :file) end - def radio(value, *, **, &) - input(*, **, type: :radio, value: value, &) + def radio(value, *, **) + input(*, **, type: :radio, value: value) end # Rails compatibility aliases diff --git a/spec/superform/rails/components/input_component_spec.rb b/spec/superform/rails/components/input_component_spec.rb index ab1dac8..60a4daa 100644 --- a/spec/superform/rails/components/input_component_spec.rb +++ b/spec/superform/rails/components/input_component_spec.rb @@ -1,4 +1,4 @@ -RSpec.describe Superform::Rails::Components::Input do +RSpec.describe Superform::Rails::Components::Input, type: :view do let(:field) do object = double("object", "foo=": nil) object = double("object", "foo": value) @@ -65,4 +65,19 @@ end it { is_expected.to have_client_provided_value } end + + describe "block handling" do + it "does not accept blocks in view_template" do + # Input is a void element and should not render block content + html = render(component) + expect(html).to eq('') + end + + it "ignores block content if accidentally passed" do + # Even if someone tries to pass a block, it should be ignored + html = render(component) { "This should not appear" } + expect(html).to eq('') + expect(html).not_to include("This should not appear") + end + end end diff --git a/spec/superform/rails/field_convenience_methods_spec.rb b/spec/superform/rails/field_convenience_methods_spec.rb index c3d9196..8c4397c 100644 --- a/spec/superform/rails/field_convenience_methods_spec.rb +++ b/spec/superform/rails/field_convenience_methods_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe Superform::Rails::Form::Field do +RSpec.describe Superform::Rails::Form::Field, type: :view do let(:user) { User.new(email: "test@example.com", first_name: "John") } let(:form) { Superform::Rails::Form.new(user) } let(:field) { form.field(:email) } @@ -60,4 +60,51 @@ expect(component.type).to eq("radio") end end + + describe "block handling" do + # Input elements are void elements and should not accept blocks. + # These tests verify that blocks are properly ignored. + + it "does not render block content for text input" do + html = render(field.text { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="text"[^>]*>/) + end + + it "does not render block content for email input" do + html = render(field.email { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="email"[^>]*>/) + end + + it "does not render block content for password input" do + html = render(field.password { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="password"[^>]*>/) + end + + it "does not render block content for hidden input" do + html = render(field.hidden { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="hidden"[^>]*>/) + end + + it "does not render block content for number input" do + html = render(field.number { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="number"[^>]*>/) + end + + it "does not render block content for date input" do + html = render(field.date { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="date"[^>]*>/) + end + + it "does not render block content for file input" do + html = render(field.file { "Block content" }) + expect(html).not_to include("Block content") + expect(html).to match(/]*type="file"[^>]*>/) + end + end end \ No newline at end of file From 59b4997f7f9a8f65beea802783e39bc23c682f1d Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Tue, 18 Nov 2025 17:20:23 -0800 Subject: [PATCH 2/2] Update Gemfile.lock --- Gemfile.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Gemfile.lock b/Gemfile.lock index 92e3849..91ae8a7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,6 +92,7 @@ GEM drb (2.2.1) erubi (1.13.1) ffi (1.17.1-arm64-darwin) + ffi (1.17.1-x86_64-darwin) ffi (1.17.1-x86_64-linux-gnu) formatador (1.1.0) globalid (1.2.1) @@ -146,6 +147,8 @@ GEM nio4r (2.7.4) nokogiri (1.18.9-arm64-darwin) racc (~> 1.4) + nokogiri (1.18.9-x86_64-darwin) + racc (~> 1.4) nokogiri (1.18.9-x86_64-linux-gnu) racc (~> 1.4) notiffany (0.1.3) @@ -233,6 +236,7 @@ GEM securerandom (0.3.1) shellany (0.0.1) sqlite3 (2.7.3-arm64-darwin) + sqlite3 (2.7.3-x86_64-darwin) sqlite3 (2.7.3-x86_64-linux-gnu) stringio (3.1.1) thor (1.3.2) @@ -252,6 +256,7 @@ PLATFORMS arm64-darwin-22 arm64-darwin-23 arm64-darwin-24 + x86_64-darwin-21 x86_64-linux DEPENDENCIES