Repository: yippee-fun/phlex (ruby)

Issue:
Remove the `<param>` element
- [ ] Issue a warning in 1.x
- [ ] Remove in 2.0


Discussion:
First item solved by: https://github.com/phlex-ruby/phlex/pull/642
@stephannv That `deprecated: true` argument is just a no-op at the moment. We need to update the generated elemen method to issue a warning if that flag is set.

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,16 +11,11 @@ jobs:
       matrix:
         os: ["ubuntu-latest", "macos-latest"]
         ruby-version:
-          - "2.7"
-          - "3.0"
-          - "3.1"
           - "3.2"
           - "3.3"
           - "head"
-          - "truffleruby-22.2"
-          - "truffleruby-22.3"
-          - "jruby-9.4.6.0"
-          - "jruby-head"
+          - "truffleruby-23.1"
+          - "truffleruby-24.0"
 
     runs-on: ${{ matrix.os }}
     steps:
diff --git a/.rubocop.yml b/.rubocop.yml
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -3,7 +3,7 @@ inherit_from:
   - "https://www.goodcop.style/tabs.yml"
 
 AllCops:
-  TargetRubyVersion: 2.7
+  TargetRubyVersion: 3.2
 
 Style/ExplicitBlockArgument:
   Enabled: false
@@ -25,3 +25,9 @@ Naming/MethodName:
 
 Style/ReturnNilInPredicateMethodDefinition:
   Enabled: false
+
+Naming/BlockForwarding:
+  Enabled: false
+
+Style/ArgumentsForwarding:
+  Enabled: false
diff --git a/fixtures/components/say_hi.rb b/fixtures/components/say_hi.rb
--- a/fixtures/components/say_hi.rb
+++ b/fixtures/components/say_hi.rb
@@ -6,7 +6,7 @@ def initialize(name, times: 1)
 		@times = times
 	end
 
-	def template
+	def view_template
 		article {
 			@times.times { h1 { "Hi #{@name}" } }
 			yield
diff --git a/lib/phlex.rb b/lib/phlex.rb
--- a/lib/phlex.rb
+++ b/lib/phlex.rb
@@ -42,15 +42,7 @@ class NameError < ::NameError
 	# @api private
 	ATTRIBUTE_CACHE = {}
 
-	SUPPORTS_FIBER_STORAGE = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.2")
-end
-
-if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
-	class Symbol
-		def name
-			to_s
-		end
-	end
+	SUPPORTS_FIBER_STORAGE = RUBY_ENGINE == "ruby"
 end
 
 def 💪
diff --git a/lib/phlex/csv.rb b/lib/phlex/csv.rb
--- a/lib/phlex/csv.rb
+++ b/lib/phlex/csv.rb
@@ -3,8 +3,8 @@
 class Phlex::CSV
 	include Phlex::Callable
 
-	FORMULA_PREFIXES = ["=", "+", "-", "@", "\t", "\r"].to_h { |prefix| [prefix, true] }.freeze
-	SPACE_CHARACTERS = [" ", "\t", "\r"].to_h { |char| [char, true] }.freeze
+	FORMULA_PREFIXES = Set["=", "+", "-", "@", "\t", "\r"].freeze
+	SPACE_CHARACTERS = Set[" ", "\t", "\r"].freeze
 
 	def initialize(collection)
 		@collection = collection
@@ -92,10 +92,6 @@ def yielder(record)
 		yield(record)
 	end
 
-	def template(...)
-		nil
-	end
-
 	# Override and set to `false` to disable rendering headers.
 	def render_headers?
 		true
@@ -120,11 +116,11 @@ def escape(value)
 		first_char = value[0]
 		last_char = value[-1]
 
-		if escape_csv_injection? && FORMULA_PREFIXES[first_char]
+		if escape_csv_injection? && FORMULA_PREFIXES.include?(first_char)
 			# Prefix a single quote to prevent Excel, Google Docs, etc. from interpreting the value as a formula.
 			# See https://owasp.org/www-community/attacks/CSV_Injection
 			%("'#{value.gsub('"', '""')}")
-		elsif (!trim_whitespace? && (SPACE_CHARACTERS[first_char] || SPACE_CHARACTERS[last_char])) || value.include?('"') || value.include?(",") || value.include?("\n")
+		elsif (!trim_whitespace? && (SPACE_CHARACTERS.include?(first_char) || SPACE_CHARACTERS.include?(last_char))) || value.include?('"') || value.include?(",") || value.include?("\n")
 			%("#{value.gsub('"', '""')}")
 		else
 			value
diff --git a/lib/phlex/elements.rb b/lib/phlex/elements.rb
--- a/lib/phlex/elements.rb
+++ b/lib/phlex/elements.rb
@@ -98,20 +98,11 @@ def #{method_name}(**attributes, &block)
 	end
 
 	# @api private
-	def register_void_element(method_name, tag: method_name.name.tr("_", "-"), deprecated: false)
-		if deprecated
-			deprecation = <<~RUBY
-				Kernel.warn "#{deprecated}"
-			RUBY
-		else
-			deprecation = ""
-		end
-
+	def register_void_element(method_name, tag: method_name.name.tr("_", "-"))
 		class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
 			# frozen_string_literal: true
 
 			def #{method_name}(**attributes)
-				#{deprecation}
 				context = @_context
 				buffer = context.buffer
 				fragment = context.fragments
diff --git a/lib/phlex/helpers.rb b/lib/phlex/helpers.rb
--- a/lib/phlex/helpers.rb
+++ b/lib/phlex/helpers.rb
@@ -1,7 +1,5 @@
 # frozen_string_literal: true
 
-require "set"
-
 module Phlex::Helpers
 	private
 
diff --git a/lib/phlex/html.rb b/lib/phlex/html.rb
--- a/lib/phlex/html.rb
+++ b/lib/phlex/html.rb
@@ -7,7 +7,7 @@ class HTML < SGML
 		autoload :VoidElements, "phlex/html/void_elements"
 
 		# A list of HTML attributes that have the potential to execute unsafe JavaScript.
-		EVENT_ATTRIBUTES = %w[onabort onafterprint onbeforeprint onbeforeunload onblur oncanplay oncanplaythrough onchange onclick oncontextmenu oncopy oncuechange oncut ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus onhashchange oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmessage onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onoffline ononline onpagehide onpageshow onpaste onpause onplay onplaying onpopstate onprogress onratechange onreset onresize onscroll onsearch onseeked onseeking onselect onstalled onstorage onsubmit onsuspend ontimeupdate ontoggle onunload onvolumechange onwaiting onwheel].to_h { [_1, true] }.freeze
+		EVENT_ATTRIBUTES = Set.new(%w[onabort onafterprint onbeforeprint onbeforeunload onblur oncanplay oncanplaythrough onchange onclick oncontextmenu oncopy oncuechange oncut ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus onhashchange oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmessage onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onoffline ononline onpagehide onpageshow onpaste onpause onplay onplaying onpopstate onprogress onratechange onreset onresize onscroll onsearch onseeked onseeking onselect onstalled onstorage onsubmit onsuspend ontimeupdate ontoggle onunload onvolumechange onwaiting onwheel]).freeze
 
 		UNBUFFERED_MUTEX = Mutex.new
 
diff --git a/lib/phlex/html/standard_elements.rb b/lib/phlex/html/standard_elements.rb
--- a/lib/phlex/html/standard_elements.rb
+++ b/lib/phlex/html/standard_elements.rb
@@ -639,7 +639,7 @@ module Phlex::HTML::StandardElements
 	# 	@return [nil]
 	# 	@yieldparam component [self]
 	# 	@see https://developer.mozilla.org/docs/Web/HTML/Element/template
-	register_element :template_tag, tag: "template"
+	register_element :template
 
 	# @!method textarea(**attributes, &content)
 	# 	Outputs a `<textarea>` tag.
diff --git a/lib/phlex/html/void_elements.rb b/lib/phlex/html/void_elements.rb
--- a/lib/phlex/html/void_elements.rb
+++ b/lib/phlex/html/void_elements.rb
@@ -58,12 +58,6 @@ module Phlex::HTML::VoidElements
 	# 	@see https://developer.mozilla.org/docs/Web/HTML/Element/meta
 	register_void_element :meta
 
-	# @!method param(**attributes, &content)
-	# 	Outputs a `<param>` tag.
-	# 	@return [nil]
-	# 	@see https://developer.mozilla.org/docs/Web/HTML/Element/param
-	register_void_element :param, deprecated: "⚠️ [DEPRECATION] The <param> tag is deprecated. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param"
-
 	# @!method source(**attributes, &content)
 	# 	Outputs a `<source>` tag.
 	# 	@return [nil]
diff --git a/lib/phlex/kit.rb b/lib/phlex/kit.rb
--- a/lib/phlex/kit.rb
+++ b/lib/phlex/kit.rb
@@ -1,11 +1,6 @@
 # frozen_string_literal: true
 
 module Phlex::Kit
-	def self.extended(mod)
-		warn "⚠️ [WARNING] Phlex::Kit is experimental and may be removed from future versions of Phlex."
-		super
-	end
-
 	# When a kit is included in a module, we need to load all of its components.
 	def included(mod)
 		constants.each { |c| const_get(c) if autoload?(c) }
diff --git a/lib/phlex/sgml.rb b/lib/phlex/sgml.rb
--- a/lib/phlex/sgml.rb
+++ b/lib/phlex/sgml.rb
@@ -16,7 +16,7 @@ def call(...)
 			def new(*args, **kwargs, &block)
 				if block
 					object = super(*args, **kwargs, &nil)
-					object.instance_variable_set(:@_content_block, block)
+					object.instance_exec { @_content_block = block }
 					object
 				else
 					super
@@ -65,18 +65,8 @@ def element_method?(method_name)
 		# 	def view_template(&block)
 		# 		article(class: "card", &block)
 		# 	end
-		def template
-			yield
-		end
-
-		def self.method_added(method_name)
-			if method_name == :template
-				Kernel.warn "⚠️ [DEPRECATION] Defining the `template` method on a Phlex component will not be supported in Phlex 2.0. Please rename the method to `view_template` instead."
-			end
-		end
-
-		def view_template(&block)
-			template(&block)
+		def view_template
+			yield if block_given?
 		end
 
 		def await(task)
@@ -105,8 +95,8 @@ def __final_call__(buffer = +"", context: Phlex::Context.new, view_context: nil,
 			@_context = context
 			@_view_context = view_context
 			@_parent = parent
+
 			if fragments
-				warn "⚠️ [WARNING] Selective Rendering is experimental, incomplete, and may change in future versions."
 				@_context.target_fragments(fragments)
 			end
 
@@ -407,7 +397,7 @@ def __final_attributes__(**attributes)
 			end
 
 			buffer = +""
-			__build_attributes__(attributes, buffer: buffer)
+			__build_attributes__(attributes, buffer:)
 
 			buffer
 		end
@@ -427,7 +417,7 @@ def __build_attributes__(attributes, buffer:)
 				next if lower_name == "href" && v.start_with?(/\s*javascript:/i)
 
 				# Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters.
-				if HTML::EVENT_ATTRIBUTES[lower_name] || name.match?(/[<>&"']/)
+				if HTML::EVENT_ATTRIBUTES.include?(lower_name) || name.match?(/[<>&"']/)
 					raise ArgumentError, "Unsafe attribute name detected: #{k}."
 				end
 
@@ -447,7 +437,7 @@ def __build_attributes__(attributes, buffer:)
 								when Symbol then"#{name}-#{subkey.name.tr('_', '-')}"
 								else "#{name}-#{subkey}"
 							end
-						}, buffer: buffer
+						}, buffer:
 					)
 				when Array
 					buffer << " " << name << '="' << Phlex::Escape.html_escape(v.compact.join(" ")) << '"'
diff --git a/phlex.gemspec b/phlex.gemspec
--- a/phlex.gemspec
+++ b/phlex.gemspec
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
 	spec.description = "A high-performance view framework optimised for fun."
 	spec.homepage = "https://www.phlex.fun"
 	spec.license = "MIT"
-	spec.required_ruby_version = ">= 2.7"
+	spec.required_ruby_version = ">= 3.2"
 
 	spec.metadata["homepage_uri"] = spec.homepage
 	spec.metadata["source_code_uri"] = "https://github.com/phlex-ruby/phlex"


Test patch:
diff --git a/lib/phlex/testing/view_helper.rb b/lib/phlex/testing/view_helper.rb
--- a/lib/phlex/testing/view_helper.rb
+++ b/lib/phlex/testing/view_helper.rb
@@ -7,7 +7,7 @@ def render(view, &block)
 				view = view.new
 			end
 
-			view.call(view_context: view_context, &block)
+			view.call(view_context:, &block)
 		end
 
 		def view_context
diff --git a/test/phlex/kit.rb b/test/phlex/kit.rb
--- a/test/phlex/kit.rb
+++ b/test/phlex/kit.rb
@@ -5,14 +5,14 @@
 class Example < Phlex::HTML
 	include Components
 
-	def template
+	def view_template
 		SayHi("Joel", times: 2) { "Inside" }
 		Components::SayHi("Will", times: 1) { "Inside" }
 	end
 end
 
 # This feature is only supported in Ruby 3.2 or later.
-if RUBY_VERSION >= "3.2"
+if Phlex::SUPPORTS_FIBER_STORAGE
 	describe Phlex::Kit do
 		it "raises when you try to render a component outside of a rendering context" do
 			expect { Components::SayHi() }.to raise_exception(RuntimeError)
diff --git a/test/phlex/view/capture.rb b/test/phlex/view/capture.rb
--- a/test/phlex/view/capture.rb
+++ b/test/phlex/view/capture.rb
@@ -76,7 +76,7 @@ def view_template
 				def view_template
 					srcdoc = capture { yield } if block_given?
 
-					iframe srcdoc: srcdoc
+					iframe srcdoc:
 				end
 			end
 		end
diff --git a/test/phlex/view/legacy_template_method.rb b/test/phlex/view/legacy_template_method.rb
deleted file mode 100644
--- a/test/phlex/view/legacy_template_method.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-describe Phlex::SGML do
-	it "warns when you define a template" do
-		expect(Kernel).to receive(:warn)
-
-		example = Class.new(Phlex::HTML) do
-			def template
-				h1 { "Hello, world!" }
-			end
-		end
-
-		expect(
-			example.new.call
-		).to be == "<h1>Hello, world!</h1>"
-	end
-end
diff --git a/test/phlex/view/naughty_business.rb b/test/phlex/view/naughty_business.rb
--- a/test/phlex/view/naughty_business.rb
+++ b/test/phlex/view/naughty_business.rb
@@ -5,7 +5,7 @@
 
 	with "naughty javascript links" do
 		view do
-			def template
+			def view_template
 				a(href: "javascript:alert(1)") { "a" }
 				a(href: "JAVASCRIPT:alert(1)") { "b" }
 				a(href: :"JAVASCRIPT:alert(1)") { "c" }
@@ -20,7 +20,7 @@ def template
 
 	with "naughty uppercase event tag" do
 		view do
-			def template
+			def view_template
 				button ONCLICK: "ALERT(1)" do
 					"naughty button"
 				end
@@ -85,7 +85,7 @@ def view_template
 		end
 	end
 
-	Phlex::HTML::EVENT_ATTRIBUTES.each_key do |event_attribute|
+	Phlex::HTML::EVENT_ATTRIBUTES.each do |event_attribute|
 		with "with naughty #{event_attribute} attribute" do
 			naughty_attributes = { event_attribute => "alert(1);" }