Handle installing Pandoc

This commit is contained in:
2025-01-09 11:25:52 -08:00
parent 3d1ea3183c
commit b8d8b3dbd8
11 changed files with 736 additions and 199 deletions

View File

@@ -1,13 +1,44 @@
defmodule Mix.Tasks.Pandoc do
use Mix.Task
@moduledoc """
Invokes pandoc with the given args.
@ext ".md"
Usage:
$ mix pandoc TASK_OPTIONS PROFILE PANDOC_ARGS
Example:
$ mix pandoc default documents/hello.md -o priv/static/posts/hello.html
If pandoc is not installed, it is automatically downloaded. Note the
arguments given to this task will be appended to any configured arguments.
## Options
* `--runtime-config` - load the runtime configuration
before executing command
Note flags to control this Mix task must be given before the profile:
$ mix pandoc --runtime-config default documents/hello.md
"""
@shortdoc "Invokes pandoc with the profile and args"
@compile {:no_warn_undefined, Mix}
use Mix.Task
@impl true
def run(args) do
switches = [runtime_config: :boolean]
{opts, remaining_args} = OptionParser.parse_head!(args, switches: switches)
if function_exported?(Mix, :ensure_application!, 1) do
Mix.ensure_application!(:inets)
Mix.ensure_application!(:ssl)
end
if opts[:runtime_config] do
Mix.Task.run("app.config")
else
@@ -19,28 +50,11 @@ defmodule Mix.Tasks.Pandoc do
install_and_run(remaining_args)
end
defp install_and_run([profile | _args] = all) do
IO.puts("Converting markdown...")
profile = String.to_atom(profile)
config = Application.get_env(:pandoc, profile)
args = config[:args] || []
opts = [cd: config[:cd] || File.cwd!()]
out_path = List.last(args)
full_out_path = [opts[:cd], out_path] |> Path.join() |> Path.expand()
File.rm_rf!(full_out_path)
File.mkdir_p!(full_out_path)
opts[:cd]
|> Path.join("*#{@ext}")
|> Path.wildcard()
|> Enum.each(fn path ->
case Pandoc.run(profile, path) do
0 -> :ok
status -> Mix.raise("`mix pandoc #{Enum.join(all, " ")}` exited with #{status}")
end
end)
defp install_and_run([profile | args] = all) do
case Pandoc.install_and_run(String.to_atom(profile), args) do
0 -> :ok
status -> Mix.raise("`mix pandoc #{Enum.join(all, " ")}` exited with #{status}")
end
end
defp install_and_run([]) do

View File

@@ -0,0 +1,70 @@
defmodule Mix.Tasks.Pandoc.Install do
@moduledoc """
Installs pandoc under `_build`.
```bash
$ mix pandoc.install
$ mix pandoc.install --if-missing
```
By default, it installs #{Pandoc.latest_version()} but you can configure it
in your config files, such as:
config :pandoc, :version, "#{Pandoc.latest_version()}"
## Options
* `--runtime-config` - load the runtime configuration before executing
command
* `--if-missing` - install only if the given version does not exist
"""
@shortdoc "Installs pandoc under _build"
@compile {:no_warn_undefined, Mix}
use Mix.Task
@impl true
def run(args) do
valid_options = [runtime_config: :boolean, if_missing: :boolean]
{opts, base_url} =
case OptionParser.parse_head!(args, strict: valid_options) do
{opts, []} ->
{opts, Pandoc.default_base_url()}
{opts, [base_url]} ->
{opts, base_url}
{_, _} ->
Mix.raise("""
Invalid arguments to pandoc.install, expected one of:
mix pandoc.install
mix pandoc.install 'https://github.com/jgm/pandoc/releases/download/$version/pandoc-$version-$target.tar.gz'
mix pandoc.install --runtime-config
mix pandoc.install --if-missing
""")
end
if opts[:runtime_config], do: Mix.Task.run("app.config")
if opts[:if_missing] && latest_version?() do
:ok
else
if function_exported?(Mix, :ensure_application!, 1) do
Mix.ensure_application!(:inets)
Mix.ensure_application!(:ssl)
end
Mix.Task.run("loadpaths")
Pandoc.install(base_url)
end
end
defp latest_version?() do
version = Pandoc.configured_version()
match?({:ok, ^version}, Pandoc.bin_version())
end
end