Skip to content

Commit b500eda

Browse files
authored
Merge pull request #22 from DefactoSoftware/pien/accept-atom-classnames
Make sure atoms can be passed onto class, class_name and class_selector
2 parents 3815e1b + 6479033 commit b500eda

File tree

2 files changed

+63
-55
lines changed

2 files changed

+63
-55
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
- v1-plt-cache-{{ checksum "mix.lock" }}
2626
- v1-plt-cache
2727
- run: mix dialyzer --plt
28+
- run: mix dialyzer --list-unused-filters
2829
- save_cache:
2930
key: v1-plt-cache-{{ checksum "mix.lock" }}
3031
paths:

lib/ex_css_modules/ex_css_modules.ex

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ defmodule ExCSSModules do
55
alias __MODULE__
66
alias Phoenix.HTML
77

8+
@type key :: String.t() | atom()
9+
@type key_tuple :: {key, as_boolean(term())}
10+
811
@doc """
912
Reads a valid stylesheet definition. Returns a map if the stylesheet is
1013
already a map. Reads the file if the stylesheet is a string. Returns an empty
@@ -28,6 +31,7 @@ defmodule ExCSSModules do
2831
%{}
2932
3033
"""
34+
@spec stylesheet(String.t() | map()) :: map()
3135
def stylesheet(definition) when is_map(definition), do: definition
3236
def stylesheet(definition), do: read_stylesheet(definition)
3337

@@ -48,112 +52,111 @@ defmodule ExCSSModules do
4852
attribute. The `keys` argument is used to retrieve the class name or multiple
4953
class names with class_name/1.
5054
55+
Returns nil if `return_class?` is falsy. `return_class?` is optional and
56+
truthy by default.
57+
5158
Returns nil for a class_name that does not exist.
5259
5360
## Examples
5461
5562
iex> class(%{ "hello" => "world"}, "hello")
5663
{:safe, ~s(class="world")}
5764
58-
iex> class(%{"hello" => "world"}, "foo")
59-
nil
60-
61-
"""
62-
def class(definition, keys) do
63-
definition
64-
|> class_name(keys)
65-
|> class_attribute()
66-
end
67-
68-
@doc """
69-
If `return_class?` is truthy, reads the class definitions and maps them to a
70-
class attribute. When `return_class?` is falsy returns nil.
71-
72-
## Examples
73-
74-
iex> class(%{ "hello" => "world"}, "hello", true)
65+
iex> class(%{ "hello" => "world"}, :hello, true)
7566
{:safe, ~s(class="world")}
7667
7768
iex> class(%{ "hello" => "world"}, "hello", false)
7869
nil
7970
71+
iex> class(%{ "hello" => "world"}, "hello", nil)
72+
nil
73+
74+
iex> class(%{"hello" => "world"}, "foo")
75+
nil
76+
8077
"""
81-
def class(definition, keys, return_class?) do
78+
@spec class(map(), key, as_boolean(term())) :: {:safe, iodata()} | nil
79+
def class(definition, keys, return_class? \\ true) do
8280
definition
8381
|> class_name(keys, return_class?)
8482
|> class_attribute()
8583
end
8684

8785
@doc """
88-
Returns the class name from the definition map if the last argument is truthy.
89-
Returns nil if the last argument is falsy.
86+
Returns the class name or class names from the definition map, concatenated as
87+
one string separated by spaces.
9088
91-
## Examples
89+
Second argument `key` can be a string or atom name of the key, a tuple with
90+
`{key, boolean}` or a list of either keys or tuples.
9291
93-
iex> class_name(%{"hello" => "world"}, "hello", true)
94-
"world"
92+
Returns nil if `return_class?` is falsy. `return_class?` is optional and
93+
truthy by default.
9594
96-
iex> class_name(%{"hello" => "world"}, "hello", "anything")
97-
"world"
95+
Returns nil for a key that does not exist.
9896
99-
iex> class_name(%{"hello" => "world"}, "hello", false)
100-
nil
101-
102-
iex> class_name(%{"hello" => "world"}, "hello", nil)
103-
nil
97+
## Examples
10498
105-
"""
106-
def class_name(_, _, false), do: nil
107-
def class_name(_, _, nil), do: nil
108-
def class_name(definition, key, _), do: class_name(definition, key)
99+
iex> class_name(%{"hello" => "world", "foo" => "bar"}, ["hello", "foo"])
100+
"world bar"
109101
110-
@doc """
111-
Returns the class name or class names from the definition map, concatenated as
112-
one string separated by spaces.
102+
iex> class_name(%{"hello" => "world", "foo" => "bar"}, [{"hello", true}, {"foo", true}])
103+
"world bar"
113104
114-
Second argument can be a string name of the key, a tuple with `{key, boolean}`
115-
or a list of keys or tuples.
105+
iex> class_name(%{"hello" => "world", "foo" => "bar"}, [{"hello", true}, {"foo", false}])
106+
"world"
116107
117-
## Examples
108+
iex> class_name(%{"hello" => "world", "foo" => "bar"}, [{:hello, true}, {:foo, false}])
109+
"world"
118110
119111
iex> class_name(%{"hello" => "world"}, "hello")
120112
"world"
121113
122-
iex> class_name(%{"hello" => "world"}, "foo")
123-
nil
114+
iex> class_name(%{"hello" => "world"}, :hello, true)
115+
"world"
116+
117+
iex> class_name(%{"hello" => "world"}, "hello", "anything")
118+
"world"
124119
125120
iex> class_name(%{"hello" => "world"}, {"hello", true})
126121
"world"
127122
128-
iex> class_name(%{"hello" => "world"}, {"hello", false})
123+
iex> class_name(%{"hello" => "world"}, "hello", false)
129124
nil
130125
131-
iex> class_name(%{"hello" => "world", "foo" => "bar"}, ["hello", "foo"])
132-
"world bar"
133-
134-
iex> class_name(%{"hello" => "world", "foo" => "bar"}, [{"hello", true}, {"foo", true}])
135-
"world bar"
136-
137-
iex> class_name(%{"hello" => "world", "foo" => "bar"}, [{"hello", true}, {"foo", false}])
138-
"world"
126+
iex> class_name(%{"hello" => "world"}, {:hello, nil})
127+
nil
139128
140-
iex> class_name(%{"hello" => "world", "foo" => "bar"}, [{"hello", false}])
129+
iex> class_name(%{"hello" => "world"}, "foo")
141130
nil
142131
143132
iex> class_name(%{}, "hello")
144133
nil
145134
146135
"""
147-
def class_name(definition, keys) when is_list(keys) do
136+
@spec class_name(map(), key | key_tuple | [key, ...] | [key_tuple, ...], as_boolean(term())) ::
137+
String.t() | nil
138+
def class_name(definition, key, return_class? \\ true)
139+
140+
def class_name(_, _, false), do: nil
141+
def class_name(_, _, nil), do: nil
142+
143+
def class_name(definition, keys, _) when is_list(keys) do
148144
keys
149145
|> Enum.map(&class_name(definition, &1))
150146
|> Enum.reject(&is_nil/1)
151147
|> join_class_name()
152148
end
153149

154-
def class_name(definition, {key, return_class?}), do: class_name(definition, key, return_class?)
150+
def class_name(definition, {key, return_class?}, _),
151+
do: class_name(definition, key, return_class?)
155152

156-
def class_name(definition, key) do
153+
def class_name(definition, key, _) when is_atom(key) do
154+
key
155+
|> Atom.to_string()
156+
|> (&class_name(definition, &1)).()
157+
end
158+
159+
def class_name(definition, key, _) do
157160
definition
158161
|> stylesheet()
159162
|> Map.get(key, nil)
@@ -177,10 +180,14 @@ defmodule ExCSSModules do
177180
iex> class_selector(%{ "hello" => "world"}, "hello")
178181
".world"
179182
183+
iex> class_selector(%{ "hello" => "world"}, :hello)
184+
".world"
185+
180186
iex> class_selector(%{ "hello" => "world", "foo" => "bar"}, ["hello", "foo"])
181187
".world.bar"
182188
183189
"""
190+
@spec class_selector(String.t() | map(), key | [key, ...]) :: String.t()
184191
def class_selector(definition, keys) when is_list(keys) do
185192
keys
186193
|> Enum.map(&class_selector(definition, &1))

0 commit comments

Comments
 (0)