Current section
Files
Jump to
Current section
Files
lib/tag.ex
defmodule Liquor.Tags.Tag do
@moduledoc """
The Tag module holds the structure for a Tag.
A Tag consist of a identification string (tag)
a URI for OpenGraph (base_url) and a pseudo
EEx template string.
"""
alias __MODULE__
defstruct ~w(tag uri template)a
@typedoc "A Tag consists of a string identification (tag), an URI and an pseudo EEx template string"
@type t :: %Tag{tag: String.t(), uri: URI.t(), template: String.t()}
@doc """
Helps creating a new Tag.
The template is a string with pseudo EEx (for safer evaluation).
The URI is a string that can be used as a base URL
for all the tags when fetching the Open Graph data.
## Examples
iex> Liquor.Tags.Tag.new("embed", "<%= og.title %>")
%Liquor.Tags.Tag{tag: "embed", template: "<%= og.title %>", uri: %URI{}}
"""
@spec new(String.t(), String.t(), String.t()) :: Tag.t()
def new(tag, template, uri \\ "") do
%Tag{tag: tag, uri: URI.parse(uri), template: template}
end
@doc """
A safer way to replace the tags
Instead of EEx.eval_string()
This function is recommended to use cases
when the user can send input.
The template string can use a pseudo EEx tags.
Example `<%= og.title %>` for rendering the
open graph data.
Check https://github.com/bitboxer/opengraph_parser/blob/main/lib/open_graph.ex#L55
for all the available keys.
## Examples
iex> Liquor.Tags.Tag.render(Liquor.Tags.Tag.new("embed", "<%= og.title %>"), [og: %OpenGraph{title: "A Sample Title"}])
"A Sample Title"
"""
@spec render(Tag.t(), list(Keyword.t())) :: String.t()
def render(%Tag{} = tag, bindings) do
og =
Keyword.get(bindings, :og, [])
|> Map.from_struct()
Enum.reduce(og, tag.template, fn {key, value}, acc ->
String.replace(
acc,
~r/<%=\s*og\.#{key}\s*%>/u,
case value do
nil -> ""
value -> to_string(value)
end
)
end)
end
end