defmodule Still.Compiler.TemplateHelpers.Link do @moduledoc """ Renders an anchor HTML tag. """ alias Still.Compiler.TemplateHelpers.ContentTag alias Still.Compiler.TemplateHelpers.UrlFor alias Still.SourceFile @doc """ Uses `Still.Compiler.TemplateHelpers.ContentTag` to render an anchor tag. Requires a `:to` option, the target URL. If this is a relative path, the website's base URL is prepended. If it is an absolute path the `target: "_blank"` and `rel: "noopener noreferrer"` options are added to be passed to `Still.Compiler.TemplateHelpers.ContentTag` `render` function. If there is a `do` block, it uses the current file preprocessor to render `markup`. Note that this is on demand, outside `Still.Compiler.CompilationStage`. """ def render(env, opts, do: markup) do preprocessor = env[:preprocessor] %{content: content} = preprocessor.render(%SourceFile{ content: markup, input_file: env[:input_file], extension: env[:extension], metadata: env |> Enum.into(%{}) }) render(env, content, opts) end def render(_env, text, opts) do {url, opts} = pop_url(opts) ContentTag.render("a", text, [{:href, url} | opts]) end defp pop_url(opts) do {to, opts} = Keyword.pop!(opts, :to) case URI.parse(to) do %URI{host: nil, scheme: nil, path: path} when not is_nil(path) -> {UrlFor.render(to), opts} %URI{scheme: scheme} when scheme in ["http", "https"] -> opts = add_absolute_path_opts(opts) {to, opts} _ -> {to, opts} end end defp add_absolute_path_opts(opts) do opts |> Keyword.put_new(:target, "_blank") |> Keyword.put_new(:rel, "noopener noreferrer") end end