Packages
surface
0.11.5
0.12.3
0.12.2
0.12.1
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.1
0.1.0
0.1.0-alpha.2
0.1.0-alpha.1
0.1.0-alpha.0
A component based library for Phoenix LiveView
Current section
Files
Jump to
Current section
Files
lib/surface/formatter/phase.ex
defmodule Surface.Formatter.Phase do
@moduledoc """
A phase implementing a single "rule" for formatting code. These work as middleware
between `Surface.Compiler.Parser.parse` and `Surface.Formatter.Render.node/2`
to modify node lists before they are rendered.
Some phases rely on other phases; `@moduledoc`s should make this explicit.
For reference, the formatter operates by running these phases in the following order:
- `Surface.Formatter.Phases.TagWhitespace`
- `Surface.Formatter.Phases.Newlines`
- `Surface.Formatter.Phases.SpacesToNewlines`
- `Surface.Formatter.Phases.Indent`
- `Surface.Formatter.Phases.FinalNewline`
- `Surface.Formatter.Phases.BlockExceptions`
- `Surface.Formatter.Phases.Render`
""" && false
alias Surface.Formatter
@doc "The function implementing the phase. Returns the given nodes with the transformation applied."
@callback run(nodes :: [Formatter.formatter_node()], opts :: [Formatter.option()]) :: [
Formatter.formatter_node()
]
@typedoc "A node that takes a list of nodes and returns them back after applying a transformation"
@type node_transformer :: (nodes -> nodes)
@typedoc "A list of nodes"
@type nodes :: [Formatter.formatter_node()]
@doc """
Given a list of nodes, find all "element" nodes (HTML elements or Surface components)
and transform children of those nodes using the given function.
Useful for recursing deeply through the entire tree of nodes.
"""
@spec transform_element_children(nodes, node_transformer) :: nodes
def transform_element_children(nodes, transform) do
Enum.map(nodes, fn
{tag, attributes, children, meta} ->
{tag, attributes, transform.(children), meta}
{:block, name, expr, children, meta} ->
{:block, name, expr, transform.(children), meta}
node ->
node
end)
end
@doc """
Given a list of nodes, find all "element" nodes (HTML elements or Surface components)
and transform children of those nodes using the given function.
Recurses deeply through the tree, unlike `transform_element_children`, which only affects
a single layer.
"""
def transform_elements_and_descendants(nodes, transform) when is_function(transform, 1) do
nodes
|> Enum.map(fn
{tag, attributes, children, meta} ->
children =
children
|> transform_elements_and_descendants(transform)
|> transform.()
{tag, attributes, children, meta}
{:block, name, expr, children, meta} ->
children =
children
|> transform_elements_and_descendants(transform)
|> transform.()
{:block, name, expr, children, meta}
node ->
node
end)
|> Enum.map(transform)
end
end