Web Dev Solutions

Catalin Mititiuc

# Pandoc A watcher and a Mix task that uses Pandoc to convert markdown files to html. ## Requirements - inotify-tools - pandoc ## Installation ```elixir # mix.exs def deps do [ {:pandoc, "~> 0.2.0", runtime: Mix.env() == :dev} ] end ``` ## Use ```elixir # mix.exs # ... defp aliases do [ # ... "documents.build": ["pandoc hello"], "statics.build": ["assets.build", "documents.build"], "statics.deploy": ["assets.deploy", "documents.build"] ] end ``` ```elixir # config/config.exs config :pandoc, hello: [ args: ~w(--mathjax -o ../priv/static/posts), cd: Path.expand("../documents", __DIR__) ] ``` ```elixir # config/dev.exs config :hello, HelloWeb.Endpoint, # ... watchers: [ # ... pandoc: {Pandoc, :run, [:hello, ~w(--watch)]} ] config :pandoc, hello: [pattern: "**/*.md"] ``` ```elixir # lib/hello_web/router.ex scope "/", HelloWeb do pipe_through :browser get "/drafts/:id", PostController, :draft get "/posts/:id", PostController, :show get "/posts", PostController, :index get "/", PageController, :home end ``` ```elixir # lib/hello_web/controllers/posts_controller.ex defmodule HelloWeb.PostController do use HelloWeb, :controller alias Hello.Document @path "documents/**/*.md" paths = Path.wildcard(@path) @paths_hash :erlang.md5(paths) for path <- paths, do: @external_resource(path) @posts Document.list() def __mix_recompile__?(), do: @path |> Path.wildcard() |> :erlang.md5() != @paths_hash def index(conn, _params) do render(conn, :index, posts: @posts) end def show(conn, %{"id" => id}) do assigns = [ post: :hello |> :code.priv_dir() |> Path.join("static/posts/#{id}.html") |> File.read!() ] render(conn, :show, assigns) end def drafts(conn, %{"id" => id}) do config = Application.get_env(:pandoc, :hello) opts = [ cd: config[:cd] || File.cwd!() ] filename = List.keyfind(@posts, id, 0) |> elem(1) |> Map.get(:filename) path = Path.join("_drafts", filename) render(conn, :show, post: "pandoc" |> System.cmd([path], opts) |> elem(0)) end ``` ```elixir # lib/hello/document.ex defmodule Stasis.Document do require Logger @ext ".md" @pattern Application.compile_env(:pandoc, [:hello, :pattern]) def list() do "documents" |> Path.join(@pattern) |> Path.wildcard() |> Enum.map(fn path -> {Path.basename(path), path} end) |> Enum.sort(fn {basename_a, _}, {basename_b, _} -> basename_a < basename_b end) |> Enum.reduce([], fn {filename, path}, acc -> id = Path.rootname(filename, @ext) data = if "_drafts" in Path.split(path), do: %{:draft, true}, else: %{} [{id, data} | acc] end) end ``` ```elixir # lib/hello_web/controllers/post_html.ex # ... defp href(filename, draft \\ false) do root = (draft && "/drafts") || "/posts" Path.join(root, filename |> Path.basename(".md")) end ``` ```heex <%= for {id, data} <- @posts do %>

<.link href={href(Path.rootname(filename), data[:draft])} method="get"> <%= id %>

<% end %> ``` ```heex <%= raw(@post) %> ```