defmodule Guaxinim do
alias Guaxinim.Internal.SourceProcessor
alias Guaxinim.Internal.SourceFormatter
alias Guaxinim.BeamInspector
alias Guaxinim.Config
import Guaxinim.Utils.Path, only: [path: 1]
alias Guaxinim.Config
require EEx
|
|
@doc
Prepare the destination directory |
def prepare_dst(config) do
|
|
Clean the already existing files (oportunity for caching) |
|
Create the destination directory |
|
Copy the static assets |
dst_static = Path.join(config.dst, "_static")
static_src =
:guaxinim
|> :code.priv_dir
|> Path.join("static")
File.cp_r!(static_src, dst_static)
:ok
end
def all_relative_files(root) do
paths = Path.wildcard(root <> "/**/*.ex") ++ Path.wildcard(root <> "/*.ex")
Enum.map(paths, fn path -> Path.relative_to(path, root) end)
end
def all_relative_dirs(root) do
child_paths =
Path.wildcard(root <> "/**")
|> Enum.filter(fn path -> File.dir?(path) end)
|> Enum.map(fn path -> Path.relative_to(path, root) end)
["" | child_paths]
end
def run() do
config = Config.from_mix()
BeamInspector.gather_data_from_modules(config)
prepare_dst(config)
config.src
|> all_relative_files
|> Enum.map(fn path -> process_file(path, config) end)
config.src
|> all_relative_dirs
|> Enum.map(fn path -> create_index_file(path, config) end)
:ok
end
def create_index_file(directory, config) do
abs_directory = Path.join(config.src, directory)
{sibling_directories, sibling_files} =
child_directories_and_files(abs_directory)
file = Path.join(directory, "index.html")
assigns = %{
project_title: config.project_title,
sibling_directories: sibling_directories,
sibling_files: sibling_files,
config: config,
file: file,
content: ""
}
html = render_code_page(assigns)
output_file = Path.join(config.dst, file)
write_with_mkdir(output_file, html)
end
def process_file(file, config) do
abs_file = Path.join(config.src, file)
root_dirname = Path.dirname(abs_file)
{sibling_directories, sibling_files} =
child_directories_and_files(root_dirname)
source = File.read!(abs_file)
data = SourceProcessor.process_source(file, source)
content = SourceFormatter.blocks_to_html(config, data)
assigns = %{
project_title: config.project_title,
sibling_directories: sibling_directories,
sibling_files: sibling_files,
config: config,
file: file,
content: content
}
html = render_code_page(assigns)
output_file = Path.join(config.dst, file <> ".html")
write_with_mkdir(output_file, html)
end
def write_with_mkdir(output_file, content) do
dirname = Path.dirname(output_file)
|
|
Ensure the directory exists.
To do this, we try to create the directory and ignore
both the |
case File.mkdir_p(dirname) do
:ok -> nil
{:error, :eexist} -> nil
end
File.write!(output_file, content)
end
def child_directories_and_files(parent_dir) do
children =
parent_dir
|> File.ls!
|> Enum.reject(fn path -> path == "index.md" end)
child_directories =
children
|> Enum.filter(fn path -> parent_dir |> Path.join(path) |> File.dir? end)
|> Enum.sort
child_files =
children
|> Enum.filter(fn path ->
full_path = Path.join(parent_dir, path)
not File.dir?(full_path) and Path.extname(path) == ".ex"
end)
|> Enum.sort
{child_directories, child_files}
end
|
|
Convenience functions to render the templates |
@external_resource "lib/guaxinim/templates/layout/master.html.eex"
EEx.function_from_file(:defp, :render_code_page,
"lib/guaxinim/templates/layout/master.html.eex",
[:assigns])
@external_resource "lib/guaxinim/templates/layout/sidebar.html.eex"
EEx.function_from_file(:defp, :render_sidebar,
"lib/guaxinim/templates/layout/sidebar.html.eex",
[:assigns])
end
|
TODO: Refactor this ASAP