Packages

Liquor Tags. Inspired by dev.to embed tags (liquid tags), takes Open Graph data from URLs and generate output using pseudo EEx templates.

Current section

Files

Jump to
liquor lib tag.ex
Raw

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