FrancisTemplate (Francis Template v0.2.0)

View Source

File-based templates with layouts and pluggable engines for Francis.

Templates live under a configurable root directory (default: priv/templates) and are rendered to a string. A route handler can return that string directly or, more commonly, send it with render/4, which sets the HTML headers for you.

Usage

defmodule MyApp do
  use Francis
  use FrancisTemplate

  # priv/templates/index.html.eex => <h1>Hello <%= @name %></h1>
  get("/", fn conn -> render(conn, "index.html.eex", name: "World") end)
end

use FrancisTemplate imports render/2,3,4 and render_to_string/1,2,3 so they read like the other Francis response helpers (html/2, json/2, ...). You can also call FrancisTemplate.render/4 fully qualified without the use.

Engines

The engine is chosen from the template's file extension. The built-in engines are FrancisTemplate.EEx for .eex, FrancisTemplate.Liquid for .liquid, and FrancisTemplate.Markdown for .md. Liquid and Markdown support are backed by the optional Solid and MDEx dependencies. See FrancisTemplate.Engine to add another engine or override a default.

Layouts

A layout is an ordinary template that wraps the rendered content, which is exposed to it as the inner_content assign:

# priv/templates/layout.html.eex
# <html><body><%= @inner_content %></body></html>

A layout.html.eex at the template root is applied to every render automatically — no configuration required. Point :layout at a different file to change it, pass :layout per render to override, or pass layout: false to render without a layout:

render(conn, "index.html.eex", [name: "World"], layout: false)

Assigns flow to both the content template and the layout, so a layout can use <%= @title %> alongside <%= @inner_content %>. The layout's engine is resolved from its own extension, so it need not match the content's engine. Because the default EEx engine does not auto-escape, the already-rendered inner_content is spliced in verbatim.

Escaping

The default FrancisTemplate.EEx engine does not auto-escape — escaping is the template's concern, consistent with Francis.ResponseHandlers.html/2. Escape untrusted assigns with Francis.HTML.escape/1 inside the template:

<p>Bio: <%= Francis.HTML.escape(@bio) %></p>

If you want auto-escaping everywhere, register an engine that wraps an escaping EEx engine (e.g. Phoenix.HTML.Engine); that keeps the dependency in your app rather than in this package.

Configuration

  • :root — directory templates are read from. Defaults to "priv/templates", resolved relative to the current working directory. In a release, set this to an absolute path (e.g. Application.app_dir(:my_app, "priv/templates")) since priv — not the directory's relative location — is what ships.

  • :engines — a map of file extension (without the dot) to an engine module implementing FrancisTemplate.Engine. Merged over the built-in EEx, Liquid, and Markdown engines.

  • :liquid — options for FrancisTemplate.Liquid. Use :parse_options for options passed to Solid.parse!/2 and :render_options for options passed to Solid.render!/3.

  • :markdown — options passed to MDEx.to_html!/2 by FrancisTemplate.Markdown. Runtime assigns are added as MDEx's :assigns option for use by plugins and pipelines.

  • :layout — the layout template (relative to :root) that wraps every render unless overridden per call. Defaults to "layout.html.eex" when that file exists, otherwise no layout.

    config :francis_template, engines: %{"up" => MyApp.UpcaseEngine}, layout: "base.html.eex"

Summary

Functions

Imports render/2,3,4 and render_to_string/1,2,3 into the calling module so they can be called bare alongside the other Francis response helpers.

Renders template and sends it as an HTML response with a 200 status code.

Renders template (a path relative to the template root) with assigns and returns the result as a binary.

Functions

__using__(opts)

(macro)

Imports render/2,3,4 and render_to_string/1,2,3 into the calling module so they can be called bare alongside the other Francis response helpers.

render(conn, template, assigns \\ %{}, opts \\ [])

@spec render(Plug.Conn.t(), String.t(), map() | keyword(), keyword()) :: Plug.Conn.t()

Renders template and sends it as an HTML response with a 200 status code.

template is a path relative to the configured template root and the engine is chosen from its file extension. assigns and opts are passed through to render_to_string/3.

Examples

get("/", fn conn -> render(conn, "index.html.eex", name: "World") end)

render_to_string(template, assigns \\ %{}, opts \\ [])

@spec render_to_string(String.t(), map() | keyword(), keyword()) :: binary()

Renders template (a path relative to the template root) with assigns and returns the result as a binary.

The engine is chosen from the template's file extension.

Options

  • :layout — a layout template to wrap the result. Overrides the :layout config. Pass false to skip a configured layout. See the "Layouts" section in FrancisTemplate.