diff --git a/lib/sukaato_web/marker.ex b/lib/sukaato_web/marker.ex new file mode 100644 index 0000000..78b2148 --- /dev/null +++ b/lib/sukaato_web/marker.ex @@ -0,0 +1,81 @@ +defmodule SukaatoWeb.Marker do + @moduledoc """ + Manages markdown files or strings and their conversion to HTML pages or posts. + """ + @rel_proj_root "." + @markdown_root Path.expand(@rel_proj_root <> "/controllers/page_md", __DIR__) + @markdown_pages Path.wildcard(@markdown_root <> "/*.md") + @markdown_posts @markdown_root <> "/users" + @site_config_file Path.expand("../../site.toml", __DIR__) + @site_config Toml.decode_file(@site_config_file) + @admin_username elem(@site_config, 1)["site"]["username"] + + @doc """ + Converts markdown and YAML frontmatter from files for pages or posts to HTML5. + """ + def render_mark(filename, category \\ :markdown_page, username \\ @admin_username) do + filename = if is_atom(filename), do: Atom.to_string(filename), else: filename + filename = if !String.contains?(filename, ".md"), do: filename <> ".md", else: filename + + markdown_paths = case category, do: (:markdown_page -> @markdown_pages; :markdown_post -> Path.wildcard(@markdown_posts <> "/" <> username <> "/posts/*.md")) + markdown_files = Enum.map(markdown_paths, fn p -> Path.basename(p) end) + + if Enum.member?(markdown_files, filename) do + markdown_filepath = @markdown_root <> "/" <> filename + + if category == :markdown_post do + markdown_filepath = if username != "" and username != nil, do: @markdown_root <> "/users/" <> username <> "/posts/" <> filename, else: Path.wildcard(@markdown_root <> "/users/*/posts/" <> filename) + post_data = if is_list(markdown_filepath), do: Enum.map(markdown_filepath, fn m -> YamlFrontMatter.parse_file(m) end), else: YamlFrontMatter.parse_file(markdown_filepath) + + if is_list(post_data) do + post_content = Enum.filter(post_data, fn m -> elem(m, 0) == :ok end) + post_content = if length(post_content) > 0, do: Enum.map(post_content, fn m -> Panpipe.to_html5(elem(m, 2)) end), else: [] + post_content = Enum.filter(post_content, fn m -> elem(m, 0) == :ok end) + frontmatter = if length(post_content) > 0, do: Enum.map(post_data, fn p -> elem(p, 1) end), else: [] + + if length(frontmatter) > 0 and length(post_content) > 0 do + {:ok, frontmatter, post_content} + else + {:error, frontmatter, post_content} + end + else + if elem(post_data, 0) == :ok do + post_content = Panpipe.to_html5(elem(post_data, 2)) + + if elem(post_content, 0) == :ok do + frontmatter = elem(post_data, 1) + {:ok, frontmatter, post_content} + end + else + frontmatter = elem(post_data, 1) + markdown = elem(post_data, 2) + {:error, frontmatter, markdown} + end + end + end + + if category == :markdown_page do + post_content = Panpipe.pandoc(input: markdown_filepath, to: :html5) + + if elem(post_content, 0) == :ok do + markup = elem(post_content, 1) + {:ok, markup} + # else + # {:error, "something's up"} + end + end + else + {:error, "no such markdown file '" <> filename <> "'"} + end + end + + def backup_marks(), do: nil + + # defp create_page(), do: nil + + # @NOTE following two functions should integrate markdown file creation and db insertion + + # defp create_post(), do: nil + + def create_mark(), do: nil +end