Embed images as Data URLs
A demo of how to customize embeds/files
to generate data URLs instead of raw constants instead.
It uses the file_type Elxir library to detect the mime types of files, so it requires Elixir to be installed.
The img/lucypride.png
is a downscaled PNG based on the original SVG from the the Gleam website repository.
You can check out the full example project here.
Example source code
Running this project will produce a images/lucy.gleam
module!
NOTE: In a real project, you would add a seperate
build
path dev dependency. This avoids issues when regenerating files that your project already depends on.
import embeds/files
import embeds/generate
import gleam/bit_array
import gleam/io
import gleam/option
import gleam/result
import gleam/string
pub fn main() {
let result =
files.generate(files.Options(
// where to get files from?
sources: [
files.Source(
// take all files from ./img (relative to the project root)
src: "./img",
// generate a module called "images.gleam"
module: "images",
// respect the directory structure
flatten: files.DontFlatten,
// regardless of how deep the directory tree is
max_depth: option.None,
// and filter out hidden files
filter: files.default_filter,
),
],
// how to convert a file into Gleam source code?
print: fn(path, data) {
// skip files if we can't detect the mime type,
// generate a Gleam constant otherwise
generate.skip_or_const({
use #(_extension, mime_type) <- result.map(get_file_type(path))
// build a data url
let bits = generate.data_to_bits(data)
let base64 = bit_array.base64_url_encode(bits, True)
let data_url = "data:" <> mime_type <> ";base64," <> base64
// convert the string to Gleam source code
string.inspect(data_url)
})
},
header: generate.default_header,
// Always regenerate
force: True,
))
case result {
Ok(Nil) -> Nil
Error(errs) -> io.println_error(generate.describe_errors(errs))
}
}
// -- EXTERNALS
fn get_file_type(path: String) -> Result(#(String, String), Nil) {
// make sure we throw away the Elixir error value
do_get_file_type(path) |> result.nil_error
}
// we use the file_type elixir library to detect mime types.
// NOTE: the error type is wrong here, be careful!
@external(erlang, "Elixir.FileType", "from_path")
fn do_get_file_type(path: String) -> Result(#(String, String), Nil)