Current section
Files
Jump to
Current section
Files
lib/panpipe.ex
defmodule Panpipe do
@moduledoc """
An Elixir wrapper around Pandoc.
The `Panpipe.Pandoc` module implements a wrapper around the Pandoc CLI.
The `Panpipe.AST.Node` behaviour defines the functions implemented by all
nodes of a Panpipe AST.
"""
alias Panpipe.Pandoc
defdelegate pandoc(input_or_opts, opts \\ nil), to: Pandoc, as: :call
defdelegate pandoc!(input_or_opts, opts \\ nil), to: Pandoc, as: :call!
defdelegate transform(node, fun), to: Panpipe.AST.Node
@doc """
Creates the Panpipe AST representation of some input.
It accepts the same arguments as `Panpipe.Pandoc.call/2` which will be called
implicitly to get the Pandoc AST representation.
The result is returned in an `ok` tuple.
"""
def ast(input_or_opts, opts \\ nil) do
with {:ok, pandoc_ast} <- Pandoc.ast(input_or_opts, opts) do
{:ok, Panpipe.Pandoc.AST.Node.to_panpipe(pandoc_ast)}
end
end
@doc """
Calls `ast/2` and delivers the result directly in success case, otherwise raises an error.
"""
def ast!(input_or_opts, opts \\ nil) do
with {:ok, result} <- ast(input_or_opts, opts) do
result
else
{:error, error} -> raise error
end
end
@doc """
Creates an `Panpipe.AST.Node` of some input without the surrounding `Document` structure.
"""
def ast_fragment(input_or_opts, opts \\ nil) do
with {:ok, pandoc_ast} <- ast(input_or_opts, opts) do
case pandoc_ast do
%Panpipe.Document{children: [%Panpipe.AST.Para{children: [fragment]}]} ->
{:ok, fragment}
%Panpipe.Document{children: [fragment]} ->
{:ok, fragment}
%Panpipe.Document{children: children} when is_list(children) ->
{:ok, %Panpipe.AST.Plain{children: children}}
_ -> {:error, "unable to extract ast_fragment from #{inspect pandoc_ast}"}
end
end
end
@doc """
Calls `ast_fragment/2` and delivers the result directly in success case, otherwise raises an error.
"""
def ast_fragment!(input_or_opts, opts \\ nil) do
with {:ok, result} <- ast_fragment(input_or_opts, opts) do
result
else
{:error, error} -> raise error
end
end
Enum.each Panpipe.Pandoc.output_formats, fn output_format ->
@doc """
Calls `pandoc/1` with the option `to: :#{to_string(output_format)}` automatically set.
It also accepts `Panpipe.AST.Node`s. `pandoc/1` will then be called with
Pandoc AST form of the node.
By default the converted output by Pandoc always ends with a newline. This
can not be what you want, esp. when you convert small fragments by passing
nodes directly. For this reason Panpipe will remove this newline by default
for inline nodes, but keeps them on block nodes. You can control whether
they should be removed manually with the `remove_trailing_newline` option.
Note: This function only works with directly passed strings or nodes. If you
want to convert a file using the `input` option, you'll have to read the file
first manually or use `pandoc/1` directly.
"""
def unquote(String.to_atom("to_" <> to_string(output_format)))(input, opts \\ []) do
Panpipe.Pandoc.Conversion.convert(input,
Keyword.put(opts, :to, unquote(output_format)))
end
end
end