Current section
Files
Jump to
Current section
Files
lib/x/ast.ex
defmodule X.Ast do
@moduledoc """
Contains X template AST type definitions and functions to work with the AST.
"""
@type cursor() :: {
column :: integer(),
row :: integer()
}
@type tag_attr() :: {
:tag_attr,
cursor(),
name :: charlist(),
value :: charlist(),
is_dynamic :: boolean()
}
@type tag_condition() :: {
condition :: :if | :else | :elseif | :unless,
cursor :: cursor(),
value :: charlist()
}
@type tag_iterator() :: {
iterator :: :for,
cursor :: cursor(),
value :: charlist()
}
@type tag_comment() :: {
:tag_comment,
cursor :: cursor(),
value :: charlist()
}
@type tag_start() :: {
:tag_start,
cursor :: cursor(),
name :: charlist(),
attributes :: [tag_attr()],
condition :: tag_condition(),
iterator :: tag_iterator(),
is_singleton :: boolean(),
is_selfclosed :: boolean(),
is_component :: boolean()
}
@type tag_end() :: {
:tag_end,
cursor :: cursor(),
name :: charlist()
}
@type tag_text() :: {
:tag_text,
cursor :: cursor(),
value :: charlist(),
is_leading_whitespace :: boolean(),
is_blank :: boolean()
}
@type tag_output() :: {
:tag_output,
cursor :: cursor(),
value :: charlist(),
is_html_escape :: boolean()
}
@type text_group :: {
:text_group,
cursor :: cursor(),
tag_name :: charlist()
}
@type token() ::
tag_start()
| tag_end()
| tag_text()
| tag_output()
| text_group()
| tag_comment()
@type leaf() :: {
token :: token(),
children :: [leaf()]
}
@doc """
Removes tailing and leading whitespace nodes from the given AST.
"""
@spec drop_whitespace([leaf()]) :: [leaf()]
def drop_whitespace(tree) do
tree
|> drop_leading_whitespace_and_reverse()
|> drop_leading_whitespace_and_reverse()
end
defp drop_leading_whitespace_and_reverse(leaf, acc \\ [])
defp drop_leading_whitespace_and_reverse([{token = {:text_group, _, _}, nested} | tail], []) do
filtered_text =
Enum.filter(nested, fn
{{:tag_text, _, _, _, is_blank}, []} -> !is_blank
_ -> true
end)
acc =
case filtered_text do
[] -> []
_ -> [{token, filtered_text}]
end
drop_leading_whitespace_and_reverse(tail, acc)
end
defp drop_leading_whitespace_and_reverse([head | tail], acc) do
drop_leading_whitespace_and_reverse(tail, [head | acc])
end
defp drop_leading_whitespace_and_reverse([], acc) do
acc
end
end