diff options
author | Danielle Maywood <danielle@maywood.me> | 2023-10-02 11:29:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-02 11:29:39 +0100 |
commit | 1240874302ec172b1018934ef5a8cba23397bc51 (patch) | |
tree | e249618b798b6cc095792f9ff66c3b95bc70c75b | |
parent | c33d49b08f73b00fbedbf79b7772912e0064a939 (diff) | |
download | lustre-1240874302ec172b1018934ef5a8cba23397bc51.tar.gz lustre-1240874302ec172b1018934ef5a8cba23397bc51.zip |
🔀 Combine class and style attributes (#15)
* Create initial implementation for merging class and style attrs
* Make changes according to feedback
* Handle boolean attributes properly
-rw-r--r-- | src/lustre/attribute.gleam | 17 | ||||
-rw-r--r-- | src/lustre/element.gleam | 37 |
2 files changed, 43 insertions, 11 deletions
diff --git a/src/lustre/attribute.gleam b/src/lustre/attribute.gleam index 6540713..a5ed765 100644 --- a/src/lustre/attribute.gleam +++ b/src/lustre/attribute.gleam @@ -7,6 +7,7 @@ import gleam/dynamic.{Dynamic} import gleam/function import gleam/int import gleam/list +import gleam/option.{None, Option, Some} import gleam/result import gleam/string import gleam/string_builder.{StringBuilder} @@ -53,27 +54,29 @@ pub fn map(attr: Attribute(a), f: fn(a) -> b) -> Attribute(b) { /// /// -pub fn to_string(attr: Attribute(msg)) -> String { +pub fn to_string_parts( + attr: Attribute(msg), +) -> Option(#(String, Option(String))) { case attr { Attribute(name, value, as_property: False) -> { case dynamic.classify(value) { - "String" -> name <> "=\"" <> dynamic.unsafe_coerce(value) <> "\"" + "String" -> Some(#(name, Some(dynamic.unsafe_coerce(value)))) // Boolean attributes are determined based on their presence, eg we don't // want to render `disabled="false"` if the value is `false` we simply // want to omit the attribute altogether. "Boolean" -> case dynamic.unsafe_coerce(value) { - True -> name - False -> "" + True -> Some(#(name, None)) + False -> None } // For everything else we'll just make a best-effort serialisation. - _ -> name <> "=\"" <> string.inspect(value) <> "\"" + _ -> Some(#(name, Some(string.inspect(value)))) } } - Attribute(_, _, as_property: True) -> "" - Event(on, _) -> "data-lustre-on:" <> on + Attribute(_, _, as_property: True) -> None + Event(on, _) -> Some(#("data-lustre-on", Some(on))) } } diff --git a/src/lustre/element.gleam b/src/lustre/element.gleam index 21191ff..83fce9a 100644 --- a/src/lustre/element.gleam +++ b/src/lustre/element.gleam @@ -4,6 +4,7 @@ // IMPORTS --------------------------------------------------------------------- import gleam/list +import gleam/option.{None, Some} import gleam/string import gleam/string_builder.{StringBuilder} import lustre/attribute.{Attribute} @@ -141,10 +142,38 @@ fn attrs_to_string_builder( html: StringBuilder, attrs: List(Attribute(msg)), ) -> StringBuilder { - use html, attr <- list.fold(attrs, html) - html - |> string_builder.append(" ") - |> string_builder.append_builder(attribute.to_string_builder(attr)) + let #(html, class, style) = { + use #(html, class, style), attr <- list.fold(attrs, #(html, "", "")) + + case attribute.to_string_parts(attr) { + Some(#("class", Some(val))) if class == "" -> #(html, val, style) + Some(#("class", Some(val))) -> #(html, class <> " " <> val, style) + Some(#("style", Some(val))) if style == "" -> #(html, class, val) + Some(#("style", Some(val))) -> #(html, class, style <> " " <> val) + Some(#(key, Some(val))) -> #( + string_builder.append(html, " " <> key <> "=\"" <> val <> "\""), + class, + style, + ) + Some(#(key, None)) -> #( + string_builder.append(html, " " <> key), + class, + style, + ) + None -> #(html, class, style) + } + } + + case class, style { + "", "" -> html + _, "" -> string_builder.append(html, " class=\"" <> class <> "\"") + "", _ -> string_builder.append(html, " style=\"" <> style <> "\"") + _, _ -> + string_builder.append( + html, + " class=\"" <> class <> "\" style=\"" <> style <> "\"", + ) + } } fn children_to_string_builder( |