Current section

Files

Jump to
tableau lib tableau yaml_front_matter.ex
Raw

lib/tableau/yaml_front_matter.ex

# Copyright (c) 2017 Sebastian De Deyne sebastiandedeyne@gmail.com
# Vendored from github.com/sebastiandedeyne/yaml_front_matter
defmodule Tableau.YamlFrontMatter.Error do
@moduledoc false
defexception message: "Error parsing yaml front matter"
end
defmodule Tableau.YamlFrontMatter do
@moduledoc false
def parse(string, opts \\ []) do
string
|> split_string()
|> process_parts(opts)
end
def parse!(string, opts \\ []) do
case parse(string, opts) do
{:ok, matter, body} -> {atomicize(matter), body}
{:error, _} -> raise Tableau.YamlFrontMatter.Error
end
end
defp split_string(string) do
split_pattern = ~r/[\s\r\n]---[\s\r\n]/s
string
|> then(&String.trim_leading(&1))
|> then(&("\n" <> &1))
|> then(&Regex.split(split_pattern, &1, parts: 3))
end
defp process_parts([_, yaml, body], opts) do
case parse_yaml(yaml, opts) do
{:ok, yaml} -> {:ok, yaml, body}
{:error, error} -> {:error, error}
end
end
defp process_parts(_, _), do: {:error, :invalid_front_matter}
defp parse_yaml(yaml, opts) do
case YamlElixir.read_from_string(yaml, opts) do
{:ok, parsed} -> {:ok, parsed}
error -> error
end
end
defp atomicize(map) when is_map(map) do
Map.new(map, fn
{k, v} when is_binary(k) -> {String.to_atom(k), atomicize(v)}
other -> other
end)
end
defp atomicize(list) when is_list(list) do
Enum.map(list, &atomicize/1)
end
defp atomicize(other), do: other
end