Skip to content

Commit

Permalink
Allow for special keys in stylesheets (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcardarella authored Dec 16, 2024
1 parent 3baed50 commit 4e7f0fc
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 15 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Allow stylsheets to define "special" key/value that can be compiled into the output asset

### Changed

* Emit stylesheets as json isntead of Elixir maps
* Emit stylesheets as json instead of Elixir maps
* pretty printing is not availabile for the time being
* Elixir 1.17 with OTP 27 is the minimum requirement

Expand Down
20 changes: 19 additions & 1 deletion lib/live_view_native/stylesheet.ex
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ defmodule LiveViewNative.Stylesheet do
format: format,
})

plugin = LiveViewNative.fetch_plugin!(format)
plugin_stylesheet = plugin.stylesheet

quote do
Module.register_attribute(__MODULE__, :import, accumulate: true)

Expand All @@ -118,6 +121,13 @@ defmodule LiveViewNative.Stylesheet do
@before_compile LiveViewNative.Stylesheet
@after_verify LiveViewNative.Stylesheet

unquote(if plugin_stylesheet do
quote do
use unquote(plugin_stylesheet)
@before_compile unquote(plugin_stylesheet)
end
end)

def compile_ast({class_or_list, style_list}) do
class_map =
class_or_list
Expand Down Expand Up @@ -147,7 +157,15 @@ defmodule LiveViewNative.Stylesheet do
{style, List.wrap(style_ast)}
end)

Map.merge(class_map, style_map)
unquote(if plugin_stylesheet do
quote do
class_map
|> Map.merge(style_map)
|> Map.merge(special())
end
else
quote do: Map.merge(class_map, style_map)
end)
end

def compile_ast(class_or_list) do
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"ex_doc": {:hex, :ex_doc, "0.35.1", "de804c590d3df2d9d5b8aec77d758b00c814b356119b3d4455e4b8a8687aecaf", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2121c6402c8d44b05622677b761371a759143b958c6c19f6558ff64d0aed40df"},
"floki": {:hex, :floki, "0.37.0", "b83e0280bbc6372f2a403b2848013650b16640cd2470aea6701f0632223d719e", [:mix], [], "hexpm", "516a0c15a69f78c47dc8e0b9b3724b29608aa6619379f91b1ffa47109b5d0dd3"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"live_view_native": {:git, "https://github.com/liveview-native/live_view_native.git", "5077bda7bf999311bee467828390912e03e74467", []},
"live_view_native": {:git, "https://github.com/liveview-native/live_view_native.git", "b7555f79bfe10b0b5e4623e2ddc45168f4d20ce8", []},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.0", "74bb8348c9b3a51d5c589bf5aebb0466a84b33274150e3b6ece1da45584afc82", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "49159b7d7d999e836bedaf09dcf35ca18b312230cf901b725a64f3f42e407983"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule MockSheetTest do

assert styles["color-blue"] == ["rule-2"]
assert styles["custom-123-456"] == ["rule-123", "rule-456"]
assert styles["special"]
end
end

Expand Down
22 changes: 11 additions & 11 deletions test/live_view_native_stylesheet_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@ defmodule LiveViewNative.StylesheetTest do
test "will compile the rules for all listed classes" do
output = MockSheet.compile_ast(["color-blue", "color-yellow"])

assert output == %{"color-blue" => ["rule-2"], "color-yellow" => ["rule-yellow"]}
assert output == %{"color-blue" => ["rule-2"], "color-yellow" => ["rule-yellow"], "special" => true}
end

test "won't fail when an class name isn't found" do
output = MockSheet.compile_ast(["foobar"])

assert output == %{}
assert output == %{"special" => true}
end

test "can compile for a single class name" do
output = MockSheet.compile_ast("color-blue")

assert output == %{"color-blue" => ["rule-2"]}
assert output == %{"color-blue" => ["rule-2"], "special" => true}
end

test "can compile custom classes using the RULES sigil" do
output = MockSheet.compile_ast("custom-123-456")

assert output == %{"custom-123-456" => ["rule-123", "rule-456"]}
assert output == %{"custom-123-456" => ["rule-123", "rule-456"], "special" => true}

output = MockSheet.compile_ast("custom-789-123")
assert output == %{"custom-789-123" => ["rule-789", "rule-123"]}
assert output == %{"custom-789-123" => ["rule-789", "rule-123"], "special" => true}
end

test "will not convert `nil` to an empty string during interpolation" do
output = MockSheet.compile_ast("nil")

assert output == %{"nil" => ["nil"]}
assert output == %{"nil" => ["nil"], "special" => true}
end

test "will capture and log any raises within `class/1` when compiling stylesheet" do
assert capture_io(:user, fn ->
assert MockSheet.compile_ast(["raise-12"]) == %{}
assert MockSheet.compile_ast(["raise-12"]) == %{"special" => true}
Logger.flush()
end) =~ "no match of right hand side value: [\"12\"]"
end
Expand All @@ -47,25 +47,25 @@ defmodule LiveViewNative.StylesheetTest do
test "single rules supported" do
output = MockSheet.compile_ast(["color-yellow"])

assert output == %{"color-yellow" => ["rule-yellow"]}
assert output == %{"color-yellow" => ["rule-yellow"], "special" => true}
end

test "multiple rules and class name pattern matching" do
output = MockSheet.compile_ast(["color-number-4"])

assert output == %{"color-number-4" => ["rule-1", "rule-24"]}
assert output == %{"color-number-4" => ["rule-1", "rule-24"], "special" => true}
end

test "can convert the output to a json string" do
output = MockSheet.compile_string(["complex"])

assert output == ~s({"complex":[["complex",{"line":33,"module":"MockSheet","file":"mock_sheet.ex"},[1,["complex_sub",{},[{"foo":"bar"}]],3]]]})
assert output == ~s({"complex":[["complex",{"line":33,"module":"MockSheet","file":"mock_sheet.ex"},[1,["complex_sub",{},[{"foo":"bar"}]],3]]],"special":true})
end

test "will not pattern match on nil or empty string" do
output = MockSheet.compile_ast(["color-number-"])

assert output == %{}
assert output == %{"special" => true}
end
end
end
17 changes: 16 additions & 1 deletion test/support/mock_client.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
defmodule MockClient do
use LiveViewNative,
format: :mock,
stylesheet: __MODULE__,
stylesheet_rules_parser: MockRulesParser,
component: MockComponent
end

defmacro __using__(_) do
quote do
@special true
end
end

defmacro __before_compile__(_env) do
quote do
def special do
%{"special" => @special}
end
end
end
end

0 comments on commit 4e7f0fc

Please sign in to comment.