# 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
<!-- lib/hello_web/controllers/post_html/index.html.heex -->
<%= for {id, data} <- @posts do %>
<p>
<.link href={href(Path.rootname(filename), data[:draft])} method="get">
<%= id %>
</.link>
</p>
<% end %>
```
```heex
<!-- lib/hello_web/controllers/post_html/show.html.heex -->
<%= raw(@post) %>
```