-
Notifications
You must be signed in to change notification settings - Fork 147
/
show.ex
117 lines (100 loc) · 2.86 KB
/
show.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
defmodule Surface.Directive.Show do
use Surface.Directive
def extract({":show", {:attribute_expr, value, expr_meta}, attr_meta}, meta) do
expr_meta = Helpers.to_meta(expr_meta, meta)
attr_meta = Helpers.to_meta(attr_meta, meta)
%AST.Directive{
module: __MODULE__,
name: :show,
value: directive_value(value, expr_meta),
meta: attr_meta
}
end
def extract({":show", value, attr_meta}, meta) do
attr_meta = Helpers.to_meta(attr_meta, meta)
%AST.Directive{
module: __MODULE__,
name: :show,
value: %AST.Literal{value: value},
meta: attr_meta
}
end
def extract(_, _), do: []
def process(%AST.Directive{value: %AST.Literal{value: value}}, node) do
add_value_to_attribute(node, :style, %AST.AttributeExpr{
value:
quote generated: true do
unquote(value)
end,
original: to_string(value),
meta: true
})
end
def process(%AST.Directive{value: %AST.AttributeExpr{} = show}, node) do
add_value_to_attribute(node, :style, show)
end
defp add_value_to_attribute(
%{attributes: attributes, meta: meta} = node,
name,
%AST.AttributeExpr{value: value, meta: show_meta} = show
) do
{%{value: style_value, meta: style_meta} = style, non_style} =
extract_or_create_attribute(attributes || [], name, meta)
updated_style_value = style_value_to_expr(style_value, style_meta)
updated_style_attribute = %{style | value: updated_style_value}
attributes = [
updated_style_attribute,
%Surface.AST.Attribute{
type: :boolean,
type_opts: [],
name: :hidden,
value: %AST.AttributeExpr{
show
| value:
quote generated: true do
not unquote(value)
end,
constant?: false
},
meta: show_meta
}
| non_style
]
%{node | attributes: attributes}
end
defp extract_or_create_attribute(attributes, attr_name, meta) do
attributes
|> Enum.split_with(fn
%{name: name} when name == attr_name -> true
_ -> false
end)
|> case do
{[style], non_style} ->
{style, non_style}
{_, non_style} ->
{%AST.Attribute{
name: :style,
type: :style,
value: %AST.Literal{value: ""},
meta: meta
}, non_style}
end
end
defp directive_value(value, meta) do
AST.AttributeExpr.new(
Surface.TypeHandler.expr_to_quoted!(value, ":show", :boolean, meta),
value,
meta
)
end
defp style_value_to_expr(%AST.Literal{value: value}, attr_meta) do
AST.AttributeExpr.new(
Surface.TypeHandler.expr_to_quoted!(Macro.to_string(value), ":style", :style, attr_meta),
value,
attr_meta
)
end
defp style_value_to_expr(attr_value, _attr_meta) do
attr_value
end
end