Packages

An Elixir library for rendering Slim-like templates.

Retired package: Deprecated - Was released temporarily while waiting for slime 1.3.1 release

Current section

Files

Jump to
jgy_slime lib slime parser text_block.ex
Raw

lib/slime/parser/text_block.ex

defmodule Slime.Parser.TextBlock do
@moduledoc "
Utilities for parsing text blocks.
"
@doc """
Given a text block and its declaration indentation level (see below),
produces a string (or a dynamic EEx tuple) that can be inserted into the tree.
nested
| Text block
that spans over multiple lines
---
^
declaration indent
"""
def render_content(lines, declaration_indent) do
lines =
case lines do
[{_, []} | rest] ->
normalize_indent(rest)
[first_line | rest] ->
[first_line | normalize_indent(rest, declaration_indent)]
end
insert_line_spacing(lines)
end
@doc """
Given a text block, returns the text without indentation.
"""
def render_without_indentation(lines) do
concat_lines(
lines,
fn {_line_indent, line_contents}, content ->
["\n" | line_contents ++ content]
end
)
end
defp normalize_indent([]), do: []
defp normalize_indent(lines) do
indents =
lines
|> Enum.map(fn {indent, _} -> indent end)
|> Enum.filter(&(&1 != 0))
min_indent =
case indents do
[] -> 0
_ -> Enum.min(indents)
end
{leading, rest} = Enum.split_while(lines, fn {indent, _} -> indent != min_indent end)
result =
leading
|> Enum.map(fn {_, content} -> {min_indent, content} end)
|> Enum.concat(rest)
normalize_indent(result, min_indent - 1)
end
defp normalize_indent(lines, declaration_indent) do
Enum.map(lines, fn {indent, content} ->
{indent - declaration_indent, content}
end)
end
defp insert_line_spacing(lines) do
concat_lines(
lines,
fn {line_indent, line_contents}, content ->
if 1 < line_indent do
["\n" | [String.duplicate(" ", line_indent - 1) | line_contents ++ content]]
else
["\n" | line_contents ++ content]
end
end
)
end
defp concat_lines([], _), do: []
defp concat_lines(lines, concat_function) do
[_leading_newline | content] = List.foldr(lines, [], concat_function)
content
end
end