-module(tale@content). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/tale/content.gleam"). -export([permalink_from_output/1, is_post_page/1, is_list_layout/1, with_output_path/3, load_pages/3]). -export_type([page_frontmatter/0, page_metadata/0, page_data/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type page_frontmatter() :: {page_frontmatter, binary(), binary(), binary(), gleam@option:option(binary()), boolean(), list(binary()), gleam@option:option(binary())}. -type page_metadata() :: {page_metadata, binary(), binary(), gleam@option:option(binary()), boolean(), list(binary()), binary(), binary()}. -type page_data() :: {page_data, binary(), binary(), binary(), binary(), binary(), page_metadata(), binary()}. -file("src/tale/content.gleam", 182). -spec relative_content_path(binary(), binary()) -> binary(). relative_content_path(Path, Content_dir) -> Prefix = <>, case gleam_stdlib:string_starts_with(Path, Prefix) of true -> gleam@string:drop_start(Path, string:length(Prefix)); false -> Path end. -file("src/tale/content.gleam", 209). -spec strip_extension(binary()) -> binary(). strip_extension(Path) -> case gleam_stdlib:string_ends_with(Path, <<".md"/utf8>>) of true -> gleam@string:drop_end(Path, 3); false -> Path end. -file("src/tale/content.gleam", 228). -spec is_section_index(binary()) -> boolean(). is_section_index(Relative) -> Stem = strip_extension(Relative), case Stem of <<"_index"/utf8>> -> true; _ -> gleam_stdlib:string_ends_with(Stem, <<"/_index"/utf8>>) end. -file("src/tale/content.gleam", 216). -spec infer_layout(binary()) -> binary(). infer_layout(Relative) -> case is_section_index(Relative) of true -> <<"home"/utf8>>; false -> case gleam_stdlib:string_starts_with(Relative, <<"posts/"/utf8>>) of true -> <<"section"/utf8>>; false -> <<"page"/utf8>> end end. -file("src/tale/content.gleam", 295). -spec capitalize_slug(binary()) -> binary(). capitalize_slug(Slug) -> Words = begin _pipe = Slug, _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<" "/utf8>>), gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<" "/utf8>>) end, case string:length(Words) of 0 -> <<"Page"/utf8>>; _ -> <<(string:uppercase(gleam@string:slice(Words, 0, 1)))/binary, (gleam@string:drop_start(Words, 1))/binary>> end. -file("src/tale/content.gleam", 283). -spec fallback_title(binary()) -> binary(). fallback_title(Relative) -> Stem = begin _pipe = Relative, _pipe@1 = strip_extension(_pipe), _pipe@2 = gleam@string:split(_pipe@1, <<"/"/utf8>>), _pipe@3 = lists:reverse(_pipe@2), _pipe@4 = gleam@list:first(_pipe@3), gleam@result:unwrap(_pipe@4, <<"Page"/utf8>>) end, capitalize_slug(Stem). -file("src/tale/content.gleam", 137). ?DOC(" Parsing Page metadata\n"). -spec parse_page_metadata(binary(), gleam@option:option(binary())) -> {ok, page_frontmatter()} | {error, binary()}. parse_page_metadata(Relative, Raw) -> Defaults = {page_frontmatter, fallback_title(Relative), <<"Page description"/utf8>>, infer_layout(Relative), none, false, [], none}, case Raw of none -> {ok, Defaults}; {some, Text} -> gleam@result:'try'( begin _pipe = tom:parse(Text), gleam@result:map_error( _pipe, fun(Err) -> <<<<<<"Unable to parse frontmatter in "/utf8, Relative/binary>>/binary, ": "/utf8>>/binary, (tale@util:describe_toml_error(Err))/binary>> end ) end, fun(Doc) -> {ok, {page_frontmatter, tale@util:get_string_or( Doc, [<<"title"/utf8>>], erlang:element(2, Defaults) ), tale@util:get_string_or( Doc, [<<"description"/utf8>>], erlang:element(3, Defaults) ), tale@util:get_string_or( Doc, [<<"layout"/utf8>>], erlang:element(4, Defaults) ), tale@util:optional_string( tom:get_string(Doc, [<<"date"/utf8>>]) ), tale@util:get_bool_or( Doc, [<<"draft"/utf8>>], erlang:element(6, Defaults) ), tale@util:get_string_list_or( Doc, [<<"tags"/utf8>>], erlang:element(7, Defaults) ), tale@util:optional_string( tom:get_string(Doc, [<<"author"/utf8>>]) )}} end ) end. -file("src/tale/content.gleam", 316). -spec fallback_slug(binary()) -> binary(). fallback_slug(Relative) -> _pipe = Relative, _pipe@1 = strip_extension(_pipe), _pipe@2 = gleam@string:split(_pipe@1, <<"/"/utf8>>), _pipe@3 = gleam@list:filter( _pipe@2, fun(Segment) -> (Segment /= <<""/utf8>>) andalso (Segment /= <<"_index"/utf8>>) end ), _pipe@4 = gleam@list:last(_pipe@3), _pipe@5 = gleam@result:unwrap(_pipe@4, <<"page"/utf8>>), tale@util:slugify(_pipe@5). -file("src/tale/content.gleam", 309). -spec slug_from_title(binary(), binary()) -> binary(). slug_from_title(Relative, Title) -> case tale@util:slugify(Title) of <<""/utf8>> -> fallback_slug(Relative); Slug -> Slug end. -file("src/tale/content.gleam", 326). -spec segments_without_extension(binary()) -> list(binary()). segments_without_extension(Relative) -> _pipe = Relative, _pipe@1 = strip_extension(_pipe), _pipe@2 = gleam@string:split(_pipe@1, <<"/"/utf8>>), gleam@list:filter(_pipe@2, fun(Segment) -> Segment /= <<""/utf8>> end). -file("src/tale/content.gleam", 333). -spec drop_last(list(binary())) -> list(binary()). drop_last(List_) -> case List_ of [] -> []; [_] -> []; [First | Rest] -> [First | drop_last(Rest)] end. -file("src/tale/content.gleam", 341). -spec parent_index_path(list(binary())) -> binary(). parent_index_path(Parents) -> case Parents of [] -> <<"index.html"/utf8>>; _ -> <<(gleam@string:join(Parents, <<"/"/utf8>>))/binary, "/index.html"/utf8>> end. -file("src/tale/content.gleam", 348). -spec build_path(list(binary()), binary()) -> binary(). build_path(Parents, Final) -> case Parents of [] -> Final; _ -> <<<<(gleam@string:join(Parents, <<"/"/utf8>>))/binary, "/"/utf8>>/binary, Final/binary>> end. -file("src/tale/content.gleam", 355). -spec slug_or_fallback(binary(), binary()) -> binary(). slug_or_fallback(Slug, Fallback) -> case Slug of <<""/utf8>> -> tale@util:slugify(Fallback); Other -> Other end. -file("src/tale/content.gleam", 190). -spec output_path_for(binary(), binary()) -> binary(). output_path_for(Relative, Slug) -> Segments = segments_without_extension(Relative), case Segments of [] -> <<"index.html"/utf8>>; Segs -> Last = begin _pipe = gleam@list:last(Segs), gleam@result:unwrap(_pipe, <<"index"/utf8>>) end, Parents = drop_last(Segs), case Last of <<"_index"/utf8>> -> parent_index_path(Parents); Other -> Final = slug_or_fallback(Slug, Other), build_path(Parents, <>) end end. -file("src/tale/content.gleam", 362). -spec path_from_segments(list(binary())) -> binary(). path_from_segments(Segments) -> case Segments of [] -> <<"/"/utf8>>; _ -> <<"/"/utf8, (gleam@string:join(Segments, <<"/"/utf8>>))/binary>> end. -file("src/tale/content.gleam", 236). -spec permalink_for_path(binary(), binary()) -> binary(). permalink_for_path(Relative, Slug) -> Segments = segments_without_extension(Relative), case Segments of [] -> <<"/"/utf8>>; Segs -> Last = begin _pipe = gleam@list:last(Segs), gleam@result:unwrap(_pipe, <<""/utf8>>) end, Parents = drop_last(Segs), case Last of <<"_index"/utf8>> -> path_from_segments(Parents); Other -> Final = slug_or_fallback(Slug, Other), path_from_segments(lists:append(Parents, [Final])) end end. -file("src/tale/content.gleam", 254). -spec permalink_from_output(binary()) -> binary(). permalink_from_output(Output_rel) -> Trimmed = case gleam_stdlib:string_ends_with(Output_rel, <<".html"/utf8>>) of true -> gleam@string:drop_end(Output_rel, 5); false -> Output_rel end, Segments = begin _pipe = Trimmed, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end) end, case Segments of [] -> <<"/"/utf8>>; Segs -> Last = begin _pipe@2 = gleam@list:last(Segs), gleam@result:unwrap(_pipe@2, <<""/utf8>>) end, Parents = drop_last(Segs), case Last of <<"index"/utf8>> -> case Parents of [] -> <<"/"/utf8>>; _ -> path_from_segments(Parents) end; Other -> path_from_segments(lists:append(Parents, [Other])) end end. -file("src/tale/content.gleam", 369). -spec is_post_page(page_data()) -> boolean(). is_post_page(Page) -> gleam_stdlib:string_starts_with(erlang:element(2, Page), <<"posts/"/utf8>>). -file("src/tale/content.gleam", 373). -spec is_list_layout(page_data()) -> boolean(). is_list_layout(Page) -> (erlang:element(6, Page) =:= <<"home"/utf8>>) orelse (erlang:element( 6, Page ) =:= <<"term"/utf8>>). -file("src/tale/content.gleam", 377). -spec with_output_path(page_data(), binary(), binary()) -> page_data(). with_output_path(Page, Root, Output_rel) -> {page_data, erlang:element(2, Page), Output_rel, <<<>/binary, Output_rel/binary>>, permalink_from_output(Output_rel), erlang:element(6, Page), erlang:element(7, Page), erlang:element(8, Page)}. -file("src/tale/content.gleam", 393). -spec render_markdown(binary()) -> binary(). render_markdown(Markdown) -> Options = begin _pipe = mork:configure(), mork:extended(_pipe, true) end, _pipe@1 = mork:parse_with_options(Options, Markdown), mork:to_html(_pipe@1). -file("src/tale/content.gleam", 91). ?DOC(" Load page\n"). -spec load_page(binary(), binary(), binary(), binary()) -> {ok, page_data()} | {error, binary()}. load_page(Root, Content_dir, Default_author, Path) -> gleam@result:'try'( begin _pipe = simplifile:read(Path), gleam@result:map_error( _pipe, fun(Err) -> <<<<<<"Unable to read "/utf8, Path/binary>>/binary, ": "/utf8>>/binary, (simplifile:describe_error(Err))/binary>> end ) end, fun(Contents) -> {extracted, Fm_text, Body} = frontmatter:extract(Contents), Relative = relative_content_path(Path, Content_dir), gleam@result:'try'( parse_page_metadata(Relative, Fm_text), fun(Meta) -> Body_html = render_markdown(Body), Slug = slug_from_title(Relative, erlang:element(2, Meta)), Output_rel = output_path_for(Relative, Slug), Output_abs = <<<>/binary, Output_rel/binary>>, Author = gleam@option:unwrap( erlang:element(8, Meta), Default_author ), Permalink = permalink_for_path(Relative, Slug), {ok, {page_data, Relative, Output_rel, Output_abs, Permalink, erlang:element(4, Meta), {page_metadata, erlang:element(2, Meta), erlang:element(3, Meta), erlang:element(5, Meta), erlang:element(6, Meta), erlang:element(7, Meta), Author, Slug}, Body_html}} end ) end ). -file("src/tale/content.gleam", 74). ?DOC(" Loads page list\n"). -spec load_page_list( binary(), binary(), binary(), list(binary()), list(page_data()) ) -> {ok, list(page_data())} | {error, binary()}. load_page_list(Root, Content_dir, Default_author, Files, Acc) -> case Files of [] -> {ok, lists:reverse(Acc)}; [File | Rest] -> gleam@result:'try'( load_page(Root, Content_dir, Default_author, File), fun(Page) -> load_page_list( Root, Content_dir, Default_author, Rest, [Page | Acc] ) end ) end. -file("src/tale/content.gleam", 54). ?DOC(" Load pages\n"). -spec load_pages(binary(), binary(), binary()) -> {ok, list(page_data())} | {error, binary()}. load_pages(Root, Content_dir, Default_author) -> gleam@result:'try'( begin _pipe = simplifile:get_files(Content_dir), gleam@result:map_error( _pipe, fun(Err) -> <<"Unable to list content: "/utf8, (simplifile:describe_error(Err))/binary>> end ) end, fun(Files) -> Md_files = begin _pipe@1 = Files, gleam@list:filter( _pipe@1, fun(Path) -> gleam_stdlib:string_ends_with(Path, <<".md"/utf8>>) end ) end, load_page_list(Root, Content_dir, Default_author, Md_files, []) end ).