Current section
Files
Jump to
Current section
Files
lib/still/utils.ex
defmodule Still.Utils do
@moduledoc """
Collection of utility functions.
"""
alias Still.SourceFile
alias Still.Compiler.Incremental.{Node, Registry}
def to_list(arg) when is_list(arg), do: arg
def to_list(arg), do: [arg]
def module_exists?(module) do
:module == elem(Code.ensure_compiled(module), 0)
end
@doc """
Checks whether a file should be ignored by Still or not.
"""
@spec ignored_file?(binary()) :: boolean()
def ignored_file?(file) do
config(:ignore_files, [])
|> Enum.any?(&ignored_file_match(file, &1))
end
defp ignored_file_match(file, match) when is_binary(match),
do: String.starts_with?(file, match)
defp ignored_file_match(file, match) do
cond do
Regex.regex?(match) -> String.match?(file, match)
true -> false
end
end
@doc """
Renders a file.
"""
@spec render_file(binary(), any()) :: list(SourceFile.t())
def render_file(input_file, opts \\ []) do
Registry.get_or_create_file_process(input_file)
|> Node.render(opts)
end
@doc """
Compiles a file.
"""
@spec compile_file(binary(), any()) :: list(SourceFile.t())
def compile_file(file, opts \\ []) do
Registry.get_or_create_file_process(file)
|> Node.compile(opts)
end
@doc """
Compiles a file's metadata.
"""
@spec compile_file_metadata(binary(), any()) :: list(SourceFile.t())
def compile_file_metadata(file, opts \\ []) do
Registry.get_or_create_file_process(file)
|> Node.compile_metadata(opts)
end
@doc """
Returns true if the given file exists in the input path. Returns false otherwise.
"""
def input_file_exists?(file) do
file
|> get_input_path()
|> File.exists?()
end
@doc """
Returns true if the modified time of the input file is different than the output file.
"""
def input_file_changed?(input_file, output_file) do
with {:ok, input_mtime} <-
input_file
|> get_input_path()
|> get_modified_time(),
{:ok, output_mtime} <-
output_file
|> get_output_path()
|> get_modified_time() do
Timex.compare(input_mtime, output_mtime) != -1
else
_ ->
true
end
end
@doc """
Returns the modified time of a given file. Errors if the file does not exist.
"""
def get_modified_time!(path) do
path
|> File.stat!()
|> Map.get(:mtime)
|> Timex.to_datetime()
end
@doc """
Returns the modified time of a given file as a `DateTime` struct or the
`:error` atom if the file doesn't exist.
"""
def get_modified_time(path) do
path
|> File.stat()
|> case do
{:ok, stat} ->
{:ok,
stat
|> Map.get(:mtime)
|> Timex.to_datetime()}
_ ->
:error
end
end
@doc """
Delegates the call to the current `Still.Image.Preprocessor.Adapter`.
"""
def get_image_info(file) do
Still.Image.Preprocessor.adapter().get_image_info(file)
end
@doc """
Returns the current input path for a given file, prepending it with the
site's `input` directory. See `get_input_path/0`.
"""
def get_input_path(%SourceFile{input_file: file}),
do: Path.join(get_input_path(), file)
def get_input_path(file), do: Path.join(get_input_path(), file)
@doc """
Returns the absolute path configured as the site's entrypoint.
This is the value set by
config :still, input: "path/to/site"
"""
def get_input_path do
config!(:input)
|> Path.expand()
end
@doc """
Returns the current output path for a given file, prepending it with the
site's `output` directory. See `get_output_path/0`.
"""
def get_output_path(%SourceFile{output_file: file}), do: Path.join(get_output_path(), file)
def get_output_path(file), do: Path.join(get_output_path(), file)
@doc """
Returns the absolute path configured as the site's output destination.
This is the value set by
config :still, output: "path/to/site"
"""
def get_output_path do
config!(:output)
|> Path.expand()
end
@doc """
Receives an absolute path and converts it to relative by trimming the site's
entrypoint directory.
"""
def get_relative_input_path(full_path) do
full_path
|> String.replace(config!(:input), "")
|> String.trim_leading("/")
end
@doc """
Receives an absolute path and converts it to relative by trimming the site's
entrypoint directory.
"""
def get_relative_output_path(full_path) do
full_path
|> String.replace(get_output_path(), "")
|> String.trim_leading("/")
end
@doc """
Returns the site's base URL.
"""
def get_base_url do
config(:base_url, "")
end
@doc """
Recursively cleans the site's output directory.
"""
def rm_output_dir do
get_output_path()
|> File.rm_rf()
end
@doc """
Creates the output directory.
"""
def mk_output_dir do
get_output_path()
|> File.mkdir_p!()
end
@doc """
Creates the directory by the given path, relative to the output directory.
"""
def mk_output_dir(path) do
get_output_path(path)
|> File.mkdir_p!()
end
@doc """
Recursively removes all files from the site's output directory.
"""
def clean_output_dir do
File.rm_rf(get_output_path())
File.mkdir!(get_output_path())
end
@doc """
Recursively removes all files from the given path, relative to the output
directory.
"""
def clean_output_dir(path) do
File.rm_rf(get_output_path(path))
File.mkdir!(get_output_path(path))
end
@doc """
Returns true when the current execution was started by #{Mix.Tasks.Still.Compile}
"""
def compilation_task? do
config(Mix.Tasks.Still.Compile.config_key(), false)
end
@doc """
Returns the value configured for `:still` by the given key. Errors if it
doesn't exist.
"""
def config!(key), do: Application.fetch_env!(:still, key)
@doc """
Returns the value configured for `:still` by the given key. Returns the
provided default if it doesn't exist.
"""
def config(key, default), do: Application.get_env(:still, key, default)
end