mix grf.build (Griffin v0.4.0)
View SourceGenerates a static website from template and layout files.
$ mix grf.build [--input INPUT] [--output OUTPUT]
Template and layout files will be read from INPUT directory and sub-folders, and output generated content to the OUTPUT directory.
Options
-in
,--input
- the path to the input directory. Defaults tosrc
.-out
,--output
- the directory where Griffin will write files to. Defaults to_site
--layouts
- the directory where the layout and partials files are kept. Defaults tolib/layouts
.--data
- the directory where global data files are stored.--passthrough-copies
- comma separated list of directories or files to copy directly to the output directory without processing. Supports wildcard paths usingPath.wildcard/1
Useful for assets files.--ignore
- comma separated list of directories or files to ignore inside the input directory.--config
- the path to the configuration file--dry-run
- disables writing to the file system. Useful for tests and debugging.--quiet
- print minimal console output--debug
- print additional debug information
Passthrough copy
Passthrough copy files are files that shouldn't be processed but simply
copied over to the output directory. This is useful for assets like images,
fonts, JavaScript and CSS.
A list of comma separated file or wildcard paths may be provided via the
--passthrough-copies
option. Here's an example:
$ mix grf.build --passthrough-copies=assets/js,fonts,images/*.{png,jpeg}
This command will copy all files in the assets/js
, fonts
and all PNG
and JPEG images in the images
directory over to the same path relative
to the output directory. In the above example and assuming the default
_site
output directory, Griffin would copy files to _site/assets/js
,
_site/fonts
and _site/images
directories, respectively.
Wildcard paths are expanded by Path.wildcard/1
and thus all options that
it supports can be used to build wildcard paths.
About passthrough copy paths
The paths mentioned in this option are not relative to the input directory, and instead are relative to the root of the Griffin project.
Ignore files
Griffin allows users to ignore specific files and/or directories via the
--ignore
option. This is useful for ignoring markdown files like readme
and changelog files that might be in the source directory and that should
not be processed. A list of comma separated file wildcard paths can be
passed using this option to ignore files or directories from processing.
Here's an example:
$ mix grf.build --ignore=src/posts/drafts,src/README.md
This command will ignore all input files from the src/posts/drafts
directory along with the src/README.md
file.
Wildcard paths are expanded by Path.wildcard/1
and thus all options that
it supports can be used to build wildcard paths.
The paths mentioned in this option are not relative to the input directory, and instead are relative to the root of the Griffin project.
Default ignores
By default Griffin imports the ignores from your .gitignore
file.
Quiet option
Griffin prints out information about files that it processed, including the
rendering engine that processed the file (only earmark
for now). For large
projects or other instances where users need minimal console output, there is
the --quiet
option.
Config file
Griffin allows passing in ad-hoc configuration files through the --config
option. This option accepts a path to a file that is then piped into
Code.eval_file/2
. Although this file can contain any Elixir code, it is
expected to return a map with the same configuration keys as those used by
Application environment. Here's an example config.ex
file that returns a
valid Griffin config:
%{
# any other config key could be set here
input: "custom_input_dir",
output: "custom_output_dir"
}
This option simplifies configuration since it doesn't rely on Application environment, and it allows for better testing.
Dry run
If you're debugging an issue or just want to test Griffin out, you can use
the --dry-run
option to run Griffin without writing to the file system.
Other options
Griffin uses other configuration options that can be changed by setting
specific application environment keys under the :griffin_ssg
application.
These other options include features that cannot be passed in as a single
CLI option like hooks, shortcodes, filters, and more.
Hooks
Hooks are a way to allow user defined functions to be called at specific stages of the website generation process. The available hook events are:
before
, executed before the build process startsafter
, executed after Griffin finishes building.
The result from invoking these hooks is not checked.
Multiple hooks of each kind can be set under
the :hooks
configuration key like so:
config :griffin_ssg,
hooks: %{
before: [
fn { directories, run_mode, output_mode } ->
# Read more below about each type of event
:ok
end
],
after: [
fn { directories, results, run_mode, output_mode } ->
# Read more below about each type of event
:ok
end
]
}
Hook event arguments
These are the arguments that are passed in to the hook events:
directories
: a map containing the current project directoriesdirectories.input
(defaults tosrc
)directories.output
(defaults to_site
)directories.layouts
(defaults tolib/layouts
)
output_mode
: currently hardcoded to "filesystem"run_mode
: currently hardcoded to "build"results
: (only avaiable on theafter
event). A list with the processed Griffin output- Each individual list item will have
{ input_path, output_path, url, content }
- Each individual list item will have
Shortcodes
Shortcodes are user definable functions that can be invoked inside layouts.
These functions enable easily reusable content. Shortcodes can be added under
the shortcodes
configuration key. Here's an example shortcode for embedding
YouTube videos:
config :griffin_ssg,
shortcodes: %{
youtube: fn slug ->
"""
<iframe width="560" height="315" src="https://www.youtube.com/embed/#{slug}"
title="YouTube video player" frameborder="0" allow="accelerometer;
autoplay; clipboard-write; encrypted-media; gyroscope;
picture-in-picture; web-share" allowfullscreen>
</iframe>
"""
end
}
This will create a youtube
assigns variable that can be referenced in
all layouts like so:
<main>
<p>Here's a classic YouTube video:</p>
<%= @youtube.("dQw4w9WgXcQ") %>
</main>
Shortcodes can be defined with an arbitrary number of arguments and they are expected to return content. They can reference variables or other shortcodes. When using shortcodes users can think about them as function components.
Filters
Filters are utility functions that can be used in layouts to transform and data into a more presentable format.
Like shortcodes, they are set in the application environment and they are processed into assigns variables that can be referred in all layouts.
Here's an example of a layout that uses an uppercase
filter:
<h1><%= @username |> @uppercase.() %></h1>
This filter can be defined in the configuration file under the :filters
configuration key:
config :griffin_ssg,
filters: %{
uppercase: &String.upcase/1
}
Filters versus Shortcodes
Both filters and shortcodes are user defined functions that generate output in some way. While shortcodes are meant to be convenient function components that generate any sort of output, filters are typically designed to be chained, so that the value returned from one filter is piped into the next filter.