Packages

A simple Elixir package for parsing user agent strings with the help of BrowserScope's UA database

Current section

Files

Jump to
user_agent_parser lib ua data.ex
Raw

lib/ua/data.ex

defmodule UA.Data do
@atoms [
:namespace, :user_agent_parsers, :os_parsers, :device_parsers,
:regex, :regex_flag, :family_replacement, :v1_replacement, :v2_replacement,
:os_replacement, :os_v1_replacement, :os_v2_replacement, :os_v3_replacement,
:device_replacement, :brand_replacement, :model_replacement
]
def preload do
data = File.stream!(Path.join([File.cwd!, "vendor", "uap-core", "regexes.yaml"]))
|> Enum.reduce([], &parse_line/2)
|> Dict.delete(:namespace)
|> Enum.map(&compile_regexps/1)
|> Enum.into(%{})
end
defp parse_line(line, acc) do
line = String.strip(line)
cond do
String.starts_with?(line, "#") || line == "" ->
acc
String.match?(line, ~r/^\w+:$/) ->
namespace = String.split(line, ":") |> hd |> String.to_existing_atom
Dict.put(acc, :namespace, namespace)
true ->
namespace = acc[:namespace]
[key, value] = String.split(line, ": ", parts: 2)
value = String.strip(value, ?')
if String.starts_with?(key, "-") do
parser = %{regex: value}
Dict.update(acc, namespace, [parser], &([parser|&1]))
else
[head|tail] = acc[namespace]
head = Dict.put(head, String.to_existing_atom(key), value)
Dict.put(acc, namespace, [head|tail])
end
end
end
defp compile_regexps({section, parsers}) do
{
section,
parsers
|> Enum.reverse
|> Enum.map(fn(parser) ->
parser
|> Dict.put(:regex, Regex.compile!(parser[:regex], parser[:regex_flag] || ""))
|> Dict.delete(:regex_flag)
end)
}
end
end