Packages

Microdata is an Elixir library for parsing microdata from a provided document. Includes helper functions, eg for looking up typed items in a document, and named properties in an item.

Current section

Files

Jump to
microdata lib helpers.ex
Raw

lib/helpers.ex

defmodule Microdata.Helpers do
@moduledoc """
`Microdata.Helpers` is a module for generic parsing helpers (ie those not coupled to the parsing mechanism).
For example, certain tags require their values to be absolute URLs.
"""
@doc """
Validates that URLs include scheme & host
## Examples
```
iex> Microdata.Helpers.validate_url("foo")
{:error, "No scheme"}
iex> Microdata.Helpers.validate_url("http://")
{:error, "No host"}
iex> Microdata.Helpers.validate_url("http://foo.com")
{:ok, "http://foo.com"}
```
"""
@spec validate_url(String.t()) :: {:error, String.t()} | {:ok, String.t()}
def validate_url(url) do
case URI.parse(url) do
%URI{scheme: nil} -> {:error, "No scheme"}
%URI{host: nil} -> {:error, "No host"}
_ -> {:ok, url}
end
end
@doc """
Helper function to determine if a passed URL is absolute. Returns true/false bools.
## Examples
```
iex> Microdata.Helpers.absolute_url?(nil)
false
iex> Microdata.Helpers.absolute_url?("path/to/page")
false
iex> Microdata.Helpers.absolute_url?("/path/to/page")
false
iex> Microdata.Helpers.absolute_url?("https://google.com")
true
```
"""
@spec absolute_url?(String.t()) :: boolean
def absolute_url?(nil), do: false
def absolute_url?(url) do
case Microdata.Helpers.validate_url(url) do
{:ok, _} -> true
_ -> false
end
end
# Microdata.Item helpers
@doc """
Parse item types from a space-separated string.
## Examples
```
iex> Microdata.Helpers.parse_item_types(nil)
nil
iex> Microdata.Helpers.parse_item_types("foo")
["foo"]
iex> Microdata.Helpers.parse_item_types("foo bar")
["foo", "bar"]
iex> Microdata.Helpers.parse_item_types("\\n\\nfoo bar baz \\n ")
["foo", "bar", "baz"]
```
"""
@spec parse_item_types(String.t()) :: [String.t()]
def parse_item_types(nil), do: nil
def parse_item_types(string), do: string |> String.trim() |> String.split(" ")
@doc """
Parse item id from a provided string.
## Examples
```
iex> Microdata.Helpers.parse_item_id(nil)
nil
iex> Microdata.Helpers.parse_item_id("\\r foo \\n")
URI.parse("foo")
iex> Microdata.Helpers.parse_item_id("https://google.com")
URI.parse("https://google.com")
```
"""
@spec parse_item_id(String.t()) :: URI.t()
def parse_item_id(nil), do: nil
def parse_item_id(string), do: string |> String.trim() |> URI.parse()
# Microdata.Property helpers
@doc """
Parse property names from a provided string.
## Examples
```
iex> Microdata.Helpers.parse_property_names(nil)
nil
iex> Microdata.Helpers.parse_property_names("bar", %Microdata.Item{types: MapSet.new(["foo"])})
["foo/bar"]
iex> Microdata.Helpers.parse_property_names("\\rbar baz bar \\n", %Microdata.Item{types: MapSet.new(["foo"])})
["foo/bar", "foo/baz"]
```
"""
@spec parse_property_names(String.t(), Microdata.Item.t()) :: [String.t()]
def parse_property_names(nil), do: nil
def parse_property_names(string, item) do
string
|> String.trim()
|> String.split(" ")
|> Enum.reduce([], fn name, names ->
parse_property_name(name, item, names)
end)
|> Enum.reverse()
end
defp parse_property_name(name, item, names) do
cond do
Enum.member?(names, name) ->
names
Microdata.Helpers.absolute_url?(name) ->
[name | names]
true ->
vocabulary = Microdata.Item.vocabulary(item)
if vocabulary != nil do
name = "#{vocabulary}#{name}"
if Enum.member?(names, name), do: names, else: [name | names]
else
[name | names]
end
end
end
end