From 86e565d3f0f81272e4f3ffca364f4f8b004ca111 Mon Sep 17 00:00:00 2001 From: Will Cosgrove Date: Thu, 3 Oct 2024 21:26:13 -0500 Subject: [PATCH] Allow recursively nested tokens in attributes (#807) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you have a component that you want to take in an attribute of a token list, like `class`, and you want your interface to be polymorphic like an element method's attributes would be, you currently need to type check the provided attribute and handle it manually. ```rb class Card < Phlex::HTML def initialize(class:) @class = grab(class:) end def view_template div(class: ["component-classes", @class]) end end ``` Before this PR, the above example will break if the person using the Card component tries to supply an array of classes, because `Array` is not a valid token type for `__nested_tokens__`. ```rb render Card.new(class: "fine") # =>
render Card.new(class: ["not-fine"]) # => 💥 ``` Now if an array is passed, it will also have `__nested_tokens__` called on it. ```rb render Card.new(class: ["now-fine"]) # =>
``` --- lib/phlex/sgml.rb | 8 ++++++++ quickdraw/sgml/attributes.test.rb | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/phlex/sgml.rb b/lib/phlex/sgml.rb index fb616455..4d686171 100644 --- a/lib/phlex/sgml.rb +++ b/lib/phlex/sgml.rb @@ -502,6 +502,14 @@ def __nested_tokens__(tokens) else buffer << token.to_s end + when Array + if token.length > 0 + if i > 0 + buffer << " " << __nested_tokens__(token) + else + buffer << __nested_tokens__(token) + end + end when nil # Do nothing else diff --git a/quickdraw/sgml/attributes.test.rb b/quickdraw/sgml/attributes.test.rb index c1e3ac0d..e96040c7 100644 --- a/quickdraw/sgml/attributes.test.rb +++ b/quickdraw/sgml/attributes.test.rb @@ -258,6 +258,24 @@ ) == %(
) end +test "_, Array(String | Array)" do + expect( + phlex { div(attribute: ["hello", ["world"]]) }, + ) == %(
) +end + +test "_, Array(Array | String)" do + expect( + phlex { div(attribute: [["hello"], "world"]) }, + ) == %(
) +end + +test "_, Array(String | EmptyArray)" do + expect( + phlex { div(attribute: ["hello", []]) }, + ) == %(
) +end + test "_, Array(*invalid*)" do expect { phlex { div(attribute: [Object.new]) }