-module(facet). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([parse/1]). -export_type([error/0, format/0, frontmatter/0, document/0]). -type error() :: empty | {parse_error, binary()}. -type format() :: toml | json | yaml. -type frontmatter() :: {frontmatter, binary(), format()}. -type document() :: {document, gleam@option:option(frontmatter()), binary()}. -spec grab_frontmatter(list(binary()), list(binary())) -> {ok, document()} | {error, error()}. grab_frontmatter(Input, Frontmatter) -> case Input of [] -> {error, {parse_error, <<"expected ending delimitor"/utf8>>}}; [<<"+++"/utf8>> | Rest] -> {ok, {document, {some, {frontmatter, gleam@string:join(Frontmatter, <<"\n"/utf8>>), toml}}, gleam@string:join(Rest, <<"\n"/utf8>>)}}; [<<"}"/utf8>> | Rest@1] -> {ok, {document, {some, {frontmatter, gleam@string:join( lists:append(Frontmatter, [<<"}"/utf8>>]), <<"\n"/utf8>> ), json}}, gleam@string:join(Rest@1, <<"\n"/utf8>>)}}; [<<"---"/utf8>> | Rest@2] -> {ok, {document, {some, {frontmatter, gleam@string:join(Frontmatter, <<"\n"/utf8>>), yaml}}, gleam@string:join(Rest@2, <<"\n"/utf8>>)}}; [Line | Rest@3] -> grab_frontmatter(Rest@3, lists:append(Frontmatter, [Line])) end. -spec parse(binary()) -> {ok, document()} | {error, error()}. parse(In) -> Lines = begin _pipe = In, gleam@string:split(_pipe, <<"\n"/utf8>>) end, case Lines of [] -> {error, empty}; [<<"+++"/utf8>> | Rest] -> grab_frontmatter(Rest, []); [<<"{"/utf8>> | Rest@1] -> grab_frontmatter(Rest@1, [<<"{"/utf8>>]); [<<"---"/utf8>> | Rest@2] -> grab_frontmatter(Rest@2, []); Rest@3 -> {ok, {document, none, gleam@string:join(Rest@3, <<"\n"/utf8>>)}} end.