@@ -0,0 +1,5 @@ | |||
[ | |||
inputs: ["lib/**/*.{ex,exs}", "mix.exs", "config/*.exs", "test/**/*.{ex,exs}"], | |||
line_length: 120, | |||
rename_deprecated_at: "1.4.5" | |||
] |
@@ -1,19 +1,21 @@ | |||
defmodule Microformats2.Items.ImpliedProperties do | |||
def parse(entry, root, url, doc) do | |||
implied_name_property(entry, root) |> | |||
implied_photo_property(root) |> | |||
implied_url_property(root, url, doc) | |||
implied_name_property(entry, root) | |||
|> implied_photo_property(root) | |||
|> implied_url_property(root, url, doc) | |||
end | |||
defp implied_url_property(entry, root, doc_url, doc) do | |||
if entry[:properties][:url] == nil do | |||
val = implied_url_attrval(root) | |||
url = if Microformats2.blank?(val) do | |||
implied_url_deep(root) | |||
else | |||
val | |||
end |> Microformats2.stripped_or_nil | |||
url = | |||
if Microformats2.blank?(val) do | |||
implied_url_deep(root) | |||
else | |||
val | |||
end | |||
|> Microformats2.stripped_or_nil() | |||
if Microformats2.blank?(url) do | |||
entry | |||
@@ -29,11 +31,13 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
if entry[:properties][:photo] == nil do | |||
val = implied_photo_attrval(root) | |||
url = if Microformats2.blank?(val) do | |||
implied_photo_deep(root) | |||
else | |||
val | |||
end |> Microformats2.stripped_or_nil | |||
url = | |||
if Microformats2.blank?(val) do | |||
implied_photo_deep(root) | |||
else | |||
val | |||
end | |||
|> Microformats2.stripped_or_nil() | |||
if Microformats2.blank?(url) do | |||
entry | |||
@@ -45,24 +49,26 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
end | |||
end | |||
defp implied_name_property(entry, root = {elem, _, _}) do | |||
if entry[:properties][:name] == nil do | |||
nam = cond do | |||
elem == "img" or elem == "area" -> | |||
Floki.attribute(root, "alt") |> List.first | |||
elem == "abbr" -> | |||
Floki.attribute(root, "title") |> List.first | |||
true -> | |||
val = implied_name_deep(root) | |||
if Microformats2.blank?(val) do | |||
Microformats2.Items.text_content(root) | |||
else | |||
val | |||
end | |||
end |> Microformats2.stripped_or_nil | |||
nam = | |||
cond do | |||
elem == "img" or elem == "area" -> | |||
Floki.attribute(root, "alt") |> List.first() | |||
elem == "abbr" -> | |||
Floki.attribute(root, "title") |> List.first() | |||
true -> | |||
val = implied_name_deep(root) | |||
if Microformats2.blank?(val) do | |||
Microformats2.Items.text_content(root) | |||
else | |||
val | |||
end | |||
end | |||
|> Microformats2.stripped_or_nil() | |||
Map.put(entry, :properties, Map.put(entry[:properties], :name, [nam])) | |||
else | |||
@@ -71,9 +77,11 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
end | |||
defp implied_name_deep({_, _, children}) do | |||
only_nodes = Enum.filter(children, | |||
fn(el) when is_bitstring(el) -> false | |||
(_) -> true end) | |||
only_nodes = | |||
Enum.filter(children, fn | |||
el when is_bitstring(el) -> false | |||
_ -> true | |||
end) | |||
if Enum.count(only_nodes) == 1 do | |||
sec_node = List.first(only_nodes) | |||
@@ -81,12 +89,14 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
attrval = implied_name_attrval(sec_node) | |||
if Microformats2.blank?(attrval) do | |||
sec_only_nodes = Enum.filter(sec_node_children, | |||
fn(el) when is_bitstring(el) -> false | |||
(_) -> true end) | |||
sec_only_nodes = | |||
Enum.filter(sec_node_children, fn | |||
el when is_bitstring(el) -> false | |||
_ -> true | |||
end) | |||
if Enum.count(sec_only_nodes) == 1 do | |||
third_node = sec_only_nodes |> List.first | |||
third_node = sec_only_nodes |> List.first() | |||
implied_name_attrval(third_node) | |||
end | |||
else | |||
@@ -96,35 +106,40 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
end | |||
defp implied_name_attrval(node = {"img", _, _}) do | |||
Floki.attribute(node, "alt") |> List.first | |||
Floki.attribute(node, "alt") |> List.first() | |||
end | |||
defp implied_name_attrval(node = {"area", _, _}) do | |||
Floki.attribute(node, "alt") |> List.first | |||
Floki.attribute(node, "alt") |> List.first() | |||
end | |||
defp implied_name_attrval(node = {"abbr", _, _}) do | |||
Floki.attribute(node, "title") |> List.first | |||
Floki.attribute(node, "title") |> List.first() | |||
end | |||
defp implied_name_attrval(_) do | |||
nil | |||
end | |||
defp implied_photo_deep(root) do | |||
imgs = direct_not_h_children_with_attr(root, "img", "src") | |||
objects = direct_not_h_children_with_attr(root, "object", "data") | |||
cond do | |||
Enum.count(imgs) == 1 -> | |||
List.first(imgs) |> Floki.attribute("src") |> List.first | |||
List.first(imgs) |> Floki.attribute("src") |> List.first() | |||
Enum.count(objects) == 1 -> | |||
List.first(objects) |> Floki.attribute("data") |> List.first | |||
List.first(objects) |> Floki.attribute("data") |> List.first() | |||
true -> | |||
{_, _, children} = root | |||
only_nodes = Enum.filter(children, | |||
fn(el) when is_bitstring(el) -> false | |||
(_) -> true end) | |||
only_nodes = | |||
Enum.filter(children, fn | |||
el when is_bitstring(el) -> false | |||
_ -> true | |||
end) | |||
if Enum.count(only_nodes) == 1 do | |||
child = List.first(children) | |||
@@ -133,9 +148,11 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
cond do | |||
Enum.count(sec_imgs) == 1 -> | |||
List.first(sec_imgs) |> Floki.attribute("src") |> List.first | |||
List.first(sec_imgs) |> Floki.attribute("src") |> List.first() | |||
Enum.count(sec_objs) == 1 -> | |||
List.first(sec_objs) |> Floki.attribute("data") |> List.first | |||
List.first(sec_objs) |> Floki.attribute("data") |> List.first() | |||
true -> | |||
nil | |||
end | |||
@@ -151,40 +168,45 @@ defmodule Microformats2.Items.ImpliedProperties do | |||
cond do | |||
Enum.count(as) == 1 -> | |||
List.first(as) |> Floki.attribute("href") |> List.first | |||
List.first(as) |> Floki.attribute("href") |> List.first() | |||
Enum.count(areas) == 1 -> | |||
List.first(areas) |> Floki.attribute("href") |> List.first | |||
List.first(areas) |> Floki.attribute("href") |> List.first() | |||
true -> | |||
nil | |||
end | |||
end | |||
defp implied_photo_attrval(node = {"img", _, _}) do | |||
Floki.attribute(node, "src") |> List.first | |||
Floki.attribute(node, "src") |> List.first() | |||
end | |||
defp implied_photo_attrval(node = {"object", _, _}) do | |||
Floki.attribute(node, "data") |> List.first | |||
Floki.attribute(node, "data") |> List.first() | |||
end | |||
defp implied_photo_attrval(_) do | |||
nil | |||
end | |||
defp direct_not_h_children_with_attr({_, _, children}, name, attr) do | |||
Enum.filter(children, | |||
fn({el, _, _}) -> el == name | |||
(v) when is_bitstring(v) -> false | |||
end) |> | |||
Enum.filter(fn(el) -> not Microformats2.is_rootlevel?(el) end) |> | |||
Enum.filter(fn(el) -> Enum.count(Floki.attribute(el, attr)) > 0 end) | |||
Enum.filter(children, fn | |||
{el, _, _} -> el == name | |||
v when is_bitstring(v) -> false | |||
end) | |||
|> Enum.filter(fn el -> not Microformats2.is_rootlevel?(el) end) | |||
|> Enum.filter(fn el -> Enum.count(Floki.attribute(el, attr)) > 0 end) | |||
end | |||
defp implied_url_attrval(node = {"a", _, _}) do | |||
Floki.attribute(node, "href") |> List.first | |||
Floki.attribute(node, "href") |> List.first() | |||
end | |||
defp implied_url_attrval(node = {"area", _, _}) do | |||
Floki.attribute(node, "href") |> List.first | |||
Floki.attribute(node, "href") |> List.first() | |||
end | |||
defp implied_url_attrval(_) do | |||
nil | |||
end | |||
@@ -5,16 +5,17 @@ defmodule Microformats2.Items do | |||
def parse([], _, _, items), do: items | |||
def parse(root, doc, url, items) do | |||
root_classes = Microformats2.attr_list(root) |> | |||
Enum.filter(fn(class_name) -> Microformats2.is_rootlevel?(class_name) end) |> | |||
Enum.sort | |||
root_classes = | |||
Microformats2.attr_list(root) | |||
|> Enum.filter(fn class_name -> Microformats2.is_rootlevel?(class_name) end) | |||
|> Enum.sort() | |||
{_, _, children} = root | |||
if not Enum.empty?(root_classes) do | |||
entry = parse_sub(children, doc, url, | |||
%{type: root_classes, | |||
properties: %{}}) |> Microformats2.Items.ImpliedProperties.parse(root, url, doc) | |||
entry = | |||
parse_sub(children, doc, url, %{type: root_classes, properties: %{}}) | |||
|> Microformats2.Items.ImpliedProperties.parse(root, url, doc) | |||
items ++ [entry] | |||
else | |||
@@ -24,19 +25,24 @@ defmodule Microformats2.Items do | |||
defp parse_sub([], _, _, item), do: item | |||
defp parse_sub([child | children], doc, url, item) when is_bitstring(child), do: parse_sub(children, doc, url, item) | |||
defp parse_sub([child = {_, _, child_children} | children], doc, url, item) do | |||
p = if Microformats2.has_a?(child, "h-") do | |||
parse(child, doc, url, []) |> List.first | |||
else | |||
[] | |||
end | |||
classes = Microformats2.attr_list(child) |> | |||
Enum.filter(fn("p-" <> _) -> true | |||
("u-" <> _) -> true | |||
("dt-" <> _) -> true | |||
("e-" <> _) -> true | |||
(_) -> false end) | |||
defp parse_sub([child = {_, _, child_children} | children], doc, url, item) do | |||
p = | |||
if Microformats2.has_a?(child, "h-") do | |||
parse(child, doc, url, []) |> List.first() | |||
else | |||
[] | |||
end | |||
classes = | |||
Microformats2.attr_list(child) | |||
|> Enum.filter(fn | |||
"p-" <> _ -> true | |||
"u-" <> _ -> true | |||
"dt-" <> _ -> true | |||
"e-" <> _ -> true | |||
_ -> false | |||
end) | |||
props = gen_prop(child, classes, item, p, doc, url) | |||
n_item = if Microformats2.is_rootlevel?(child), do: props, else: parse_sub(child_children, doc, url, props) | |||
@@ -47,45 +53,53 @@ defmodule Microformats2.Items do | |||
defp parse_prop("p-" <> _, child, _, _) do | |||
# TODO value pattern parsing | |||
{elem, _, _} = child | |||
title = Floki.attribute(child, "title") |> List.first | |||
alt = Floki.attribute(child, "alt") |> List.first | |||
title = Floki.attribute(child, "title") |> List.first() | |||
alt = Floki.attribute(child, "alt") |> List.first() | |||
cond do | |||
elem == "abbr" and not Microformats2.blank?(title) -> | |||
title | |||
elem == "img" and not Microformats2.blank?(alt) -> | |||
alt | |||
true -> | |||
text_content(child) |> String.trim | |||
text_content(child) |> String.trim() | |||
end | |||
end | |||
defp parse_prop("u-" <> _, child = {elem, _, _}, doc, url) do | |||
href = Floki.attribute(child, "href") |> List.first | |||
src = Floki.attribute(child, "src") |> List.first | |||
data = Floki.attribute(child, "data") |> List.first | |||
poster = Floki.attribute(child, "poster") |> List.first | |||
title = Floki.attribute(child, "title") |> List.first | |||
value = Floki.attribute(child, "value") |> List.first | |||
href = Floki.attribute(child, "href") |> List.first() | |||
src = Floki.attribute(child, "src") |> List.first() | |||
data = Floki.attribute(child, "data") |> List.first() | |||
poster = Floki.attribute(child, "poster") |> List.first() | |||
title = Floki.attribute(child, "title") |> List.first() | |||
value = Floki.attribute(child, "value") |> List.first() | |||
cond do | |||
Enum.member?(["a", "area"], elem) and not Microformats2.blank?(href) -> | |||
href | |||
Enum.member?(["img", "audio", "video", "source"], elem) and not Microformats2.blank?(src) -> | |||
src | |||
elem == "object" and not Microformats2.blank?(data) -> | |||
data | |||
elem == "video" and not Microformats2.blank?(poster) -> | |||
poster | |||
# TODO value-class-pattern at this position | |||
# TODO value-class-pattern at this position | |||
elem == "abbr" and not Microformats2.blank?(title) -> | |||
title | |||
Enum.member?(["data", "input"], elem) and not Microformats2.blank?(value) -> | |||
value | |||
true -> | |||
text_content(child) |> String.trim | |||
end |> Microformats2.abs_uri(url, doc) | |||
text_content(child) |> String.trim() | |||
end | |||
|> Microformats2.abs_uri(url, doc) | |||
end | |||
defp parse_prop("dt-" <> _, child = {elem, _, _}, _, _) do | |||
@@ -95,33 +109,41 @@ defmodule Microformats2.Items do | |||
cond do | |||
Enum.member?(["time", "ins", "del"], elem) and not Microformats2.blank?(dt) -> | |||
dt |> List.first | |||
dt |> List.first() | |||
elem == "abbr" and not Microformats2.blank?(title) -> | |||
title |> List.first | |||
title |> List.first() | |||
Enum.member?(["data", "input"], elem) and not Microformats2.blank?(value) -> | |||
value |> List.first | |||
value |> List.first() | |||
true -> | |||
text_content(child) |> String.trim | |||
text_content(child) |> String.trim() | |||
end | |||
end | |||
defp parse_prop("e-" <> _, child = {_, _, children}, _, _) do | |||
%{html: Microformats2.stripped_or_nil(Floki.raw_html(children)), | |||
text: Microformats2.stripped_or_nil(Floki.text(child))} | |||
%{ | |||
html: Microformats2.stripped_or_nil(Floki.raw_html(children)), | |||
text: Microformats2.stripped_or_nil(Floki.text(child)) | |||
} | |||
end | |||
defp parse_prop(_, _, _, _), do: nil | |||
defp get_value(class, p) do | |||
cond do | |||
Microformats2.is_a?(class, "p") and p[:properties][:name] != nil -> | |||
List.first(p[:properties][:name]) | |||
Microformats2.is_a?(class, "u") and p[:properties][:url] != nil -> | |||
List.first(p[:properties][:url]) | |||
Microformats2.is_a?(class, "e") -> #and p[:properties][:url] != nil -> | |||
# and p[:properties][:url] != nil -> | |||
Microformats2.is_a?(class, "e") -> | |||
# TODO handle | |||
nil | |||
true -> | |||
# TODO handle | |||
nil | |||
@@ -129,17 +151,19 @@ defmodule Microformats2.Items do | |||
end | |||
defp gen_prop(child, classes, item, p, doc, url) do | |||
props = Enum.reduce(classes, item[:properties], fn(class, acc) -> | |||
prop = if Microformats2.is_rootlevel?(child) do | |||
Map.put(p, :value, get_value(class, p)) | |||
else | |||
parse_prop(class, child, doc, url) | |||
end | |||
key = strip_prefix(class) |> to_key |> String.to_atom | |||
val = if acc[key] != nil, do: acc[key], else: [] | |||
Map.put(acc, key, val ++ [prop]) | |||
end) | |||
props = | |||
Enum.reduce(classes, item[:properties], fn class, acc -> | |||
prop = | |||
if Microformats2.is_rootlevel?(child) do | |||
Map.put(p, :value, get_value(class, p)) | |||
else | |||
parse_prop(class, child, doc, url) | |||
end | |||
key = strip_prefix(class) |> to_key |> String.to_atom() | |||
val = if acc[key] != nil, do: acc[key], else: [] | |||
Map.put(acc, key, val ++ [prop]) | |||
end) | |||
if Microformats2.blank?(classes) and not Microformats2.blank?(p) and Microformats2.is_rootlevel?(child) do | |||
Map.put(item, :children, (item[:children] || []) ++ [p]) | |||
@@ -148,40 +172,48 @@ defmodule Microformats2.Items do | |||
end | |||
end | |||
defp strip_prefix("p-" <> rest) do | |||
rest | |||
end | |||
defp strip_prefix("u-" <> rest) do | |||
rest | |||
end | |||
defp strip_prefix("dt-" <> rest) do | |||
rest | |||
end | |||
defp strip_prefix("e-" <> rest) do | |||
rest | |||
end | |||
defp strip_prefix(rest) do | |||
rest | |||
end | |||
def text_content(child, text \\ "") | |||
def text_content(child = {elem, _, children}, text) do | |||
txt = if elem == "img" do | |||
alt = Floki.attribute(child, "alt") | |||
if alt != nil and alt != "" do | |||
alt | |||
txt = | |||
if elem == "img" do | |||
alt = Floki.attribute(child, "alt") | |||
if alt != nil and alt != "" do | |||
alt | |||
else | |||
Floki.attribute(child, "src") | |||
end | |||
|> List.first() | |||
else | |||
Floki.attribute(child, "src") | |||
end |> List.first | |||
else | |||
"" | |||
end | |||
"" | |||
end | |||
Enum.reduce(children, text <> txt, fn(child, acc) -> | |||
Enum.reduce(children, text <> txt, fn child, acc -> | |||
text_content(child, acc) | |||
end) | |||
end | |||
def text_content(child, text) when is_bitstring(child) do | |||
text <> child | |||
end | |||
@@ -1,7 +1,6 @@ | |||
defmodule Microformats2 do | |||
def parse(url) do | |||
response = HTTPotion.get url, [ follow_redirects: true ] | |||
response = HTTPotion.get(url, follow_redirects: true) | |||
if HTTPotion.Response.success?(response) do | |||
parse(response.body, url) | |||
@@ -11,11 +10,12 @@ defmodule Microformats2 do | |||
end | |||
def parse(content, url) do | |||
doc = Floki.parse(content) |> | |||
Floki.filter_out("template") |> | |||
Floki.filter_out("style") |> | |||
Floki.filter_out("script") |> | |||
Floki.filter_out(:comment) | |||
doc = | |||
Floki.parse(content) | |||
|> Floki.filter_out("template") | |||
|> Floki.filter_out("style") | |||
|> Floki.filter_out("script") | |||
|> Floki.filter_out(:comment) | |||
rels = Microformats2.Rels.parse(doc, url) | |||
items = Microformats2.Items.parse(doc, doc, url) | |||
@@ -24,7 +24,7 @@ defmodule Microformats2 do | |||
end | |||
def attr_list(node, attr \\ "class") do | |||
Floki.attribute(node, attr) |> List.first |> to_string |> String.split(" ", trim: true) | |||
Floki.attribute(node, attr) |> List.first() |> to_string |> String.split(" ", trim: true) | |||
end | |||
def blank?(nil), do: true | |||
@@ -36,14 +36,14 @@ defmodule Microformats2 do | |||
def stripped_or_nil(val), do: String.trim(val) | |||
def is_rootlevel?(node) when is_tuple(node) do | |||
attr_list(node, "class") |> | |||
Enum.any?(fn(cls) -> is_a?(cls, "h") end) | |||
attr_list(node, "class") | |||
|> Enum.any?(fn cls -> is_a?(cls, "h") end) | |||
end | |||
def is_rootlevel?(class_name) when is_bitstring(class_name) do | |||
is_a?(class_name, "h") | |||
end | |||
def is_a?("h-" <> _, wanted), do: wanted == "h" | |||
def is_a?("p-" <> _, wanted), do: wanted == "p" | |||
def is_a?("e-" <> _, wanted), do: wanted == "e" | |||
@@ -52,7 +52,7 @@ defmodule Microformats2 do | |||
def is_a?(_, _), do: false | |||
def has_a?(node, wanted) do | |||
attr_list(node) |> Enum.filter(fn(class) -> is_a?(class, wanted) end) |> blank? | |||
attr_list(node) |> Enum.filter(fn class -> is_a?(class, wanted) end) |> blank? | |||
end | |||
def abs_uri(url, base_url, doc) do | |||
@@ -60,19 +60,23 @@ defmodule Microformats2 do | |||
parsed_base = URI.parse(base_url) | |||
cond do | |||
not Microformats2.blank?(parsed.scheme) -> # absolute URI | |||
# absolute URI | |||
not Microformats2.blank?(parsed.scheme) -> | |||
url | |||
Microformats2.blank?(parsed.scheme) and not Microformats2.blank?(parsed.host) -> # protocol relative URI | |||
# protocol relative URI | |||
Microformats2.blank?(parsed.scheme) and not Microformats2.blank?(parsed.host) -> | |||
URI.to_string(%{parsed | scheme: parsed_base.scheme}) | |||
true -> | |||
base_element = Floki.find(doc, "base") | |||
new_base = if base_element == nil or Microformats2.blank?(Floki.attribute(base_element, "href")) do | |||
base_url | |||
else | |||
abs_uri(Floki.attribute(base_element, "href") |> List.first, | |||
base_url, []) | |||
end | |||
new_base = | |||
if base_element == nil or Microformats2.blank?(Floki.attribute(base_element, "href")) do | |||
base_url | |||
else | |||
abs_uri(Floki.attribute(base_element, "href") |> List.first(), base_url, []) | |||
end | |||
parsed_new_base = URI.parse(new_base) | |||
new_path = Path.expand(parsed.path || "/", Path.dirname(parsed_new_base.path || "/")) | |||
@@ -1,46 +1,45 @@ | |||
defmodule Microformats2.Rels do | |||
def parse(doc, base_url) do | |||
link_rels = Floki.find(doc, "[rel][href]") |> | |||
Enum.filter(fn(element) -> | |||
rel = Floki.attribute(element, "rel") |> List.first | |||
href = Floki.attribute(element, "href") |> List.first | |||
link_rels = | |||
Floki.find(doc, "[rel][href]") | |||
|> Enum.filter(fn element -> | |||
rel = Floki.attribute(element, "rel") |> List.first() | |||
href = Floki.attribute(element, "href") |> List.first() | |||
String.trim(to_string(rel)) != "" and String.trim(to_string(href)) != "" | |||
end) |> | |||
Enum.reduce(%{rels: %{}, rel_urls: %{}}, fn(element, acc) -> | |||
end) | |||
|> Enum.reduce(%{rels: %{}, rel_urls: %{}}, fn element, acc -> | |||
rel = Microformats2.attr_list(element, "rel") | |||
url = Floki.attribute(element, "href") |> List.first |> Microformats2.abs_uri(base_url, doc) | |||
url = Floki.attribute(element, "href") |> List.first() |> Microformats2.abs_uri(base_url, doc) | |||
acc |> | |||
save_urls_by_rels(rel, url) |> | |||
save_rels_by_urls(rel, url) |> | |||
save_attributes(element, url) | |||
acc | |||
|> save_urls_by_rels(rel, url) | |||
|> save_rels_by_urls(rel, url) | |||
|> save_attributes(element, url) | |||
end) | |||
link_rels | |||
end | |||
defp save_urls_by_rels(map, rel, url) do | |||
Enum.reduce(rel, map, fn(rel, nmap) -> | |||
Enum.reduce(rel, map, fn rel, nmap -> | |||
if nmap[:rels][rel] == nil do | |||
Map.put(nmap, :rels, | |||
Map.put(nmap[:rels], rel, [url])) | |||
Map.put(nmap, :rels, Map.put(nmap[:rels], rel, [url])) | |||
else | |||
Map.put(nmap, :rels, | |||
Map.put(nmap[:rels], rel, | |||
Enum.uniq(nmap[:rels][rel] ++ [url]))) | |||
Map.put(nmap, :rels, Map.put(nmap[:rels], rel, Enum.uniq(nmap[:rels][rel] ++ [url]))) | |||
end | |||
end) | |||
end | |||
defp save_rels_by_urls(map, rel, url) do | |||
if map[:rel_urls][url] == nil do | |||
Map.put(map, :rel_urls, | |||
Map.put(map[:rel_urls], url, %{rels: rel})) | |||
Map.put(map, :rel_urls, Map.put(map[:rel_urls], url, %{rels: rel})) | |||
else | |||
Map.put(map, :rel_urls, | |||
Map.put(map[:rel_urls], url, | |||
Map.put(map[:rel_urls][url], :rels, Enum.uniq(map[:rel_urls][url][:rels] ++ rel)))) | |||
Map.put( | |||
map, | |||
:rel_urls, | |||
Map.put(map[:rel_urls], url, Map.put(map[:rel_urls][url], :rels, Enum.uniq(map[:rel_urls][url][:rels] ++ rel))) | |||
) | |||
end | |||
end | |||
@@ -50,25 +49,19 @@ defmodule Microformats2.Rels do | |||
if String.trim(to_string(text)) == "" or map[:rel_urls][url][:text] != nil do | |||
map | |||
else | |||
Map.put(map, :rel_urls, | |||
Map.put(map[:rel_urls], url, | |||
Map.put(map[:rel_urls][url], :text, text))) | |||
Map.put(map, :rel_urls, Map.put(map[:rel_urls], url, Map.put(map[:rel_urls][url], :text, text))) | |||
end | |||
end | |||
defp save_attributes(map, element, url) do | |||
Enum.reduce(["hreflang", "media", "title", "type"], | |||
save_text(map, element, url), | |||
fn(att, nmap) -> | |||
val = Floki.attribute(element, att) |> List.first | |||
Enum.reduce(["hreflang", "media", "title", "type"], save_text(map, element, url), fn att, nmap -> | |||
val = Floki.attribute(element, att) |> List.first() | |||
if String.trim(to_string(val)) == "" or nmap[:rel_urls][url][String.to_atom(att)] != nil do | |||
nmap | |||
else | |||
Map.put(nmap, :rel_urls, | |||
Map.put(nmap[:rel_urls], url, | |||
Map.put(nmap[:rel_urls][url], String.to_atom(att), val))) | |||
end | |||
end) | |||
if String.trim(to_string(val)) == "" or nmap[:rel_urls][url][String.to_atom(att)] != nil do | |||
nmap | |||
else | |||
Map.put(nmap, :rel_urls, Map.put(nmap[:rel_urls], url, Map.put(nmap[:rel_urls][url], String.to_atom(att), val))) | |||
end | |||
end) | |||
end | |||
end |
@@ -2,14 +2,16 @@ defmodule Microformats2.Mixfile do | |||
use Mix.Project | |||
def project do | |||
[app: :microformats2, | |||
version: "0.0.8", | |||
elixir: "~> 1.3", | |||
build_embedded: Mix.env == :prod, | |||
start_permanent: Mix.env == :prod, | |||
description: description(), | |||
package: package(), | |||
deps: deps()] | |||
[ | |||
app: :microformats2, | |||
version: "0.0.8", | |||
elixir: "~> 1.3", | |||
build_embedded: Mix.env() == :prod, | |||
start_permanent: Mix.env() == :prod, | |||
description: description(), | |||
package: package(), | |||
deps: deps() | |||
] | |||
end | |||
# Configuration for the OTP application | |||
@@ -26,10 +28,12 @@ defmodule Microformats2.Mixfile do | |||
end | |||
def package do | |||
[files: ["lib", "mix.exs", "README.md", "LICENSE"], | |||
maintainers: ["Christian Kruse"], | |||
licenses: ["AGPL 3.0"], | |||
links: %{"GitHub" => "https://github.com/ckruse/microformats2-elixir"}] | |||
[ | |||
files: ["lib", "mix.exs", "README.md", "LICENSE"], | |||
maintainers: ["Christian Kruse"], | |||
licenses: ["AGPL 3.0"], | |||
links: %{"GitHub" => "https://github.com/ckruse/microformats2-elixir"} | |||
] | |||
end | |||
# Dependencies can be Hex packages: | |||
@@ -42,8 +46,6 @@ defmodule Microformats2.Mixfile do | |||
# | |||
# Type "mix help deps" for more examples and options | |||
defp deps do | |||
[{:floki, "~> 0.7"}, | |||
{:httpotion, "~> 3.0"}, | |||
{:ex_doc, ">= 0.0.0", only: :dev}] | |||
[{:floki, "~> 0.7"}, {:httpotion, "~> 3.0"}, {:ex_doc, ">= 0.0.0", only: :dev}] | |||
end | |||
end |
@@ -4,169 +4,280 @@ defmodule Microformats2ItemsTest do | |||
test "successfully parses a whole document" do | |||
str = """ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<title>Blub</title> | |||
</head> | |||
<body> | |||
<h1>Blah</h1> | |||
<article class="h-card"> | |||
<span class="p-name">Luke <span>lulu</span></span> | |||
<a href="blub" class="u-url">blah</a> | |||
</article> | |||
</body> | |||
</html> | |||
""" | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<title>Blub</title> | |||
</head> | |||
<body> | |||
<h1>Blah</h1> | |||
<article class="h-card"> | |||
<span class="p-name">Luke <span>lulu</span></span> | |||
<a href="blub" class="u-url">blah</a> | |||
</article> | |||
</body> | |||
</html> | |||
""" | |||
ret = Microformats2.parse(str, "http://localhost") | |||
assert not Enum.empty?(ret[:items]) | |||
end | |||
test "minimal h-card" do | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Frances Berriman"]}}]} = | |||
Microformats2.parse("<span class=\"h-card\">Frances Berriman</span>", | |||
"http://localhost") | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Ben Ward"], | |||
url: ["http://benward.me"]}}]} = | |||
Microformats2.parse("<a class=\"h-card\" href=\"http://benward.me\">Ben Ward</a>", | |||
"http://localhost") | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Rohit Khare"], | |||
url: ["http://rohit.khare.org/"], | |||
photo: ["https://s3.amazonaws.com/twitter_production/profile_images/53307499/180px-Rohit-sq_bigger.jpg"]}}]} = | |||
Microformats2.parse(""" | |||
<a class="h-card" href="http://rohit.khare.org/"> | |||
<img alt="Rohit Khare" | |||
src="https://s3.amazonaws.com/twitter_production/profile_images/53307499/180px-Rohit-sq_bigger.jpg"> | |||
</a> | |||
""", | |||
"http://localhost") | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{name: ["Frances Berriman"]}}]} = | |||
Microformats2.parse("<span class=\"h-card\">Frances Berriman</span>", "http://localhost") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [%{type: ["h-card"], properties: %{name: ["Ben Ward"], url: ["http://benward.me"]}}] | |||
} = Microformats2.parse("<a class=\"h-card\" href=\"http://benward.me\">Ben Ward</a>", "http://localhost") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-card"], | |||
properties: %{ | |||
name: ["Rohit Khare"], | |||
url: ["http://rohit.khare.org/"], | |||
photo: [ | |||
"https://s3.amazonaws.com/twitter_production/profile_images/53307499/180px-Rohit-sq_bigger.jpg" | |||
] | |||
} | |||
} | |||
] | |||
} = | |||
Microformats2.parse( | |||
""" | |||
<a class="h-card" href="http://rohit.khare.org/"> | |||
<img alt="Rohit Khare" | |||
src="https://s3.amazonaws.com/twitter_production/profile_images/53307499/180px-Rohit-sq_bigger.jpg"> | |||
</a> | |||
""", | |||
"http://localhost" | |||
) | |||
end | |||
test "successfully parses a h-card with author name" do | |||
{:ok, str} = File.read "./test/documents/h_card_with_author.html" | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
photo: ["https://webfwd.org/content/about-experts/300.mitchellbaker/mentor_mbaker.jpg"], | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/", | |||
"https://twitter.com/MitchellBaker"], | |||
org: ["Mozilla Foundation"], | |||
note: ["Mitchell is responsible for setting the direction and scope of the Mozilla Foundation and its activities."], | |||
category: ["Strategy", | |||
"Leadership"]}}]} = Microformats2.parse(str, "http://localhost") | |||
{:ok, str} = File.read("./test/documents/h_card_with_author.html") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-card"], | |||
properties: %{ | |||
photo: ["https://webfwd.org/content/about-experts/300.mitchellbaker/mentor_mbaker.jpg"], | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/", "https://twitter.com/MitchellBaker"], | |||
org: ["Mozilla Foundation"], | |||
note: [ | |||
"Mitchell is responsible for setting the direction and scope of the Mozilla Foundation and its activities." | |||
], | |||
category: ["Strategy", "Leadership"] | |||
} | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
test "successfully parses a h-event combined with h-card" do | |||
{:ok, str} = File.read "./test/documents/h_event_combined_h_card.html" | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-event"], properties: %{ | |||
name: ["IndieWebCamp 2012"], | |||
url: ["http://indiewebcamp.com/2012"], | |||
start: ["2012-06-30"], | |||
end: ["2012-07-01"], | |||
location: [%{value: "Geoloqi", | |||
type: ["h-card"], | |||
properties: %{name: ["Geoloqi"], | |||
org: ["Geoloqi"], | |||
url: ["http://geoloqi.com/"], | |||
street_address: ["920 SW 3rd Ave. Suite 400"], | |||
locality: ["Portland"], | |||
region: ["Oregon"]}}]}}]} = Microformats2.parse(str, "http://localhost") | |||
{:ok, str} = File.read("./test/documents/h_event_combined_h_card.html") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-event"], | |||
properties: %{ | |||
name: ["IndieWebCamp 2012"], | |||
url: ["http://indiewebcamp.com/2012"], | |||
start: ["2012-06-30"], | |||
end: ["2012-07-01"], | |||
location: [ | |||
%{ | |||
value: "Geoloqi", | |||
type: ["h-card"], | |||
properties: %{ | |||
name: ["Geoloqi"], | |||
org: ["Geoloqi"], | |||
url: ["http://geoloqi.com/"], | |||
street_address: ["920 SW 3rd Ave. Suite 400"], | |||
locality: ["Portland"], | |||
region: ["Oregon"] | |||
} | |||
} | |||
] | |||
} | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
test "successfully parses a h-card with org" do | |||
{:ok, str} = File.read "./test/documents/h_card_org.html" | |||
{:ok, str} = File.read("./test/documents/h_card_org.html") | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"], | |||
org: ["Mozilla Foundation"]}}]} = Microformats2.parse(str, "http://localhost") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-card"], | |||
properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"], | |||
org: ["Mozilla Foundation"] | |||
} | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
test "successfully parses a h-card with h-card and org" do | |||
{:ok, str} = File.read "./test/documents/h_card_with_h_card_org.html" | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"], | |||
org: [%{value: "Mozilla Foundation", | |||
type: ["h-card"], | |||
properties: %{ | |||
name: ["Mozilla Foundation"], | |||
url: ["http://mozilla.org/"]}}]}}]} = Microformats2.parse(str, "http://localhost") | |||
{:ok, str} = File.read("./test/documents/h_card_with_h_card_org.html") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-card"], | |||
properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"], | |||
org: [ | |||
%{ | |||
value: "Mozilla Foundation", | |||
type: ["h-card"], | |||
properties: %{name: ["Mozilla Foundation"], url: ["http://mozilla.org/"]} | |||
} | |||
] | |||
} | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
test "successfully parses a nested h-card h-org h-card" do | |||
{:ok, str} = File.read "./test/documents/nested_h_card_h_org_h_card.html" | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"], | |||
org: [%{ | |||
value: "Mozilla Foundation", | |||
type: ["h-card", "h-org"], | |||
properties: %{ | |||
name: ["Mozilla Foundation"], | |||
url: ["http://mozilla.org/"]}}]}}]} = Microformats2.parse(str, "http://localhost") | |||
{:ok, str} = File.read("./test/documents/nested_h_card_h_org_h_card.html") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-card"], | |||
properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"], | |||
org: [ | |||
%{ | |||
value: "Mozilla Foundation", | |||
type: ["h-card", "h-org"], | |||
properties: %{name: ["Mozilla Foundation"], url: ["http://mozilla.org/"]} | |||
} | |||
] | |||
} | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
test "successfully parses a nested h-card w/o attached property" do | |||
{:ok, str} = File.read "./test/documents/h_card_org_h_card.html" | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Mitchell Baker"], | |||
url: ["http://blog.lizardwrangler.com/"]}, | |||
children: [%{type: ["h-card"], properties: %{ | |||
name: ["Mozilla Foundation"], | |||
url: ["http://mozilla.org/"]}}]}]} = | |||
Microformats2.parse(str, "http://localhost") | |||
{:ok, str} = File.read("./test/documents/h_card_org_h_card.html") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
type: ["h-card"], | |||
properties: %{name: ["Mitchell Baker"], url: ["http://blog.lizardwrangler.com/"]}, | |||
children: [ | |||
%{type: ["h-card"], properties: %{name: ["Mozilla Foundation"], url: ["http://mozilla.org/"]}} | |||
] | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
test "resolves explicit url to absolute URL" do | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Ben Ward"], | |||
url: ["http://benward.me/foo"]}}]} = | |||
Microformats2.parse("<div class=\"h-card\"><a class=\"u-url\" href=\"/foo\">Ben Ward</a></div>", | |||
"http://benward.me") | |||
assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ | |||
name: ["Ben Ward"], | |||
url: ["http://benward.me/foo"]}}]} = | |||
Microformats2.parse("<div class=\"h-card\"><a href=\"/foo\">Ben Ward</a></div>", | |||
"http://benward.me") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [%{type: ["h-card"], properties: %{name: ["Ben Ward"], url: ["http://benward.me/foo"]}}] | |||
} = | |||
Microformats2.parse( | |||
"<div class=\"h-card\"><a class=\"u-url\" href=\"/foo\">Ben Ward</a></div>", | |||
"http://benward.me" | |||
) | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [%{type: ["h-card"], properties: %{name: ["Ben Ward"], url: ["http://benward.me/foo"]}}] | |||
} = Microformats2.parse("<div class=\"h-card\"><a href=\"/foo\">Ben Ward</a></div>", "http://benward.me") | |||
end | |||
test "jeena entry" do | |||
{:ok, str} = File.read "./test/documents/real_world_note.html" | |||
assert %{rels: _, rel_urls: _, | |||
items: [%{properties: | |||
%{author: [%{properties: %{name: ["Jeena"], | |||
photo: ["http://localhost/avatar.jpg"], | |||
url: ["http://localhost/"]}, | |||
type: ["h-card"], value: "Jeena"}], | |||
comment: [%{properties: %{ | |||
author: [%{properties: %{name: ["Christian Kruse"], | |||
photo: ["http://localhost/cache?size=40x40>&url=https%3A%2F%2Fwwwtech.de%2Fimages%2Fchristian-kruse-242470c34a3671da4cab3e3b0d941729.jpg%3Fvsn%3Dd"], | |||
url: ["https://wwwtech.de/notes/132"]}, | |||
type: ["h-card"], | |||
value: "Christian Kruse"}], | |||
content: [%{html: "Of course he is!", | |||
text: "Of course he is!"}], | |||
name: ["Christian Kruse,\n\t\t 4 days ago\n\t\t Of course he is!"], | |||
published: ["2016-02-19T10:50:17Z"], | |||
url: ["https://wwwtech.de/notes/132"]}, type: ["h-cite"], | |||
value: "Christian Kruse,\n\t\t 4 days ago\n\t\t Of course he is!"}], | |||
content: [%{html: "<p>He's right, you know?</p>", | |||
text: "He's right, you know?"}], | |||
in_reply_to: ["https://wwwtech.de/pictures/51"], name: ["Note #587"], | |||
published: ["2016-02-18T19:33:25Z"], updated: ["2016-02-18T19:33:25Z"], | |||
url: ["http://localhost/comments/587"]}, type: ["h-as-note", "h-entry"]}]} = Microformats2.parse(str, "http://localhost") | |||
{:ok, str} = File.read("./test/documents/real_world_note.html") | |||
assert %{ | |||
rels: _, | |||
rel_urls: _, | |||
items: [ | |||
%{ | |||
properties: %{ | |||
author: [ | |||
%{ | |||
properties: %{ | |||
name: ["Jeena"], | |||
photo: ["http://localhost/avatar.jpg"], | |||
url: ["http://localhost/"] | |||
}, | |||
type: ["h-card"], | |||
value: "Jeena" | |||
} | |||
], | |||
comment: [ | |||
%{ | |||
properties: %{ | |||
author: [ | |||
%{ | |||
properties: %{ | |||
name: ["Christian Kruse"], | |||
photo: [ | |||
"http://localhost/cache?size=40x40>&url=https%3A%2F%2Fwwwtech.de%2Fimages%2Fchristian-kruse-242470c34a3671da4cab3e3b0d941729.jpg%3Fvsn%3Dd" | |||
], | |||
url: ["https://wwwtech.de/notes/132"] | |||
}, | |||
type: ["h-card"], | |||
value: "Christian Kruse" | |||
} | |||
], | |||
content: [%{html: "Of course he is!", text: "Of course he is!"}], | |||
name: ["Christian Kruse,\n\t\t 4 days ago\n\t\t Of course he is!"], | |||
published: ["2016-02-19T10:50:17Z"], | |||
url: ["https://wwwtech.de/notes/132"] | |||
}, | |||
type: ["h-cite"], | |||
value: "Christian Kruse,\n\t\t 4 days ago\n\t\t Of course he is!" | |||
} | |||
], | |||
content: [%{html: "<p>He's right, you know?</p>", text: "He's right, you know?"}], | |||
in_reply_to: ["https://wwwtech.de/pictures/51"], | |||
name: ["Note #587"], | |||
published: ["2016-02-18T19:33:25Z"], | |||
updated: ["2016-02-18T19:33:25Z"], | |||
url: ["http://localhost/comments/587"] | |||
}, | |||
type: ["h-as-note", "h-entry"] | |||
} | |||
] | |||
} = Microformats2.parse(str, "http://localhost") | |||
end | |||
end |
@@ -3,133 +3,175 @@ defmodule Microformats2RelsTest do | |||
doctest Microformats2.Rels | |||
test "parse successfully parses rels" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], text: "blub" }}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" href=\"http://blub\">blub</a>", | |||
"http://localhost")) | |||
assert( | |||
%{items: _, rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" href=\"http://blub\">blub</a>", "http://localhost") | |||
) | |||
end | |||
test "parse successfully parses multiple rels" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], text: "blub" }, | |||
"http://blah" => %{ rels: ["me"], text: "blub" }}, | |||
rels: %{"me" => ["http://blub", "http://blah"]}} = | |||
Microformats2.parse(""" | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
<a rel=\"me\" href=\"http://blah\">blub</a> | |||
""", | |||
"http://localhost")) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}, "http://blah" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://blub", "http://blah"]} | |||
} = | |||
Microformats2.parse( | |||
""" | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
<a rel=\"me\" href=\"http://blah\">blub</a> | |||
""", | |||
"http://localhost" | |||
) | |||
) | |||
end | |||
test "parse only saves one URL" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse(""" | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
""", | |||
"http://localhost")) | |||
assert( | |||
%{items: _, rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse( | |||
""" | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
""", | |||
"http://localhost" | |||
) | |||
) | |||
end | |||
test "parse saves all rels" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me", "moo"], text: "blub" }}, | |||
rels: %{"me" => ["http://blub"], | |||
"moo" => ["http://blub"]}} = | |||
Microformats2.parse(""" | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
<a rel=\"moo\" href=\"http://blub\">blub</a> | |||
""", | |||
"http://localhost")) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me", "moo"], text: "blub"}}, | |||
rels: %{"me" => ["http://blub"], "moo" => ["http://blub"]} | |||
} = | |||
Microformats2.parse( | |||
""" | |||
<a rel=\"me\" href=\"http://blub\">blub</a> | |||
<a rel=\"moo\" href=\"http://blub\">blub</a> | |||
""", | |||
"http://localhost" | |||
) | |||
) | |||
end | |||
test "parse successfully parses rels with attributes" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], media: "video", text: "blub" }}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" media=\"video\" href=\"http://blub\">blub</a>", | |||
"http://localhost")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], hreflang: "de", text: "blub" }}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" hreflang=\"de\" href=\"http://blub\">blub</a>", | |||
"http://localhost")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], title: "blub", text: "blub" }}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" title=\"blub\" href=\"http://blub\">blub</a>", | |||
"http://localhost")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], type: "text/html", text: "blub" }}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" type=\"text/html\" href=\"http://blub\">blub</a>", | |||
"http://localhost")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{ rels: ["me"], | |||
media: "video", | |||
title: "blub", | |||
hreflang: "de", | |||
type: "text/html", | |||
text: "blub" }}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" hreflang=\"de\" media=\"video\" title=\"blub\" type=\"text/html\" href=\"http://blub\">blub</a>", | |||
"http://localhost")) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], media: "video", text: "blub"}}, | |||
rels: %{"me" => ["http://blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" media=\"video\" href=\"http://blub\">blub</a>", "http://localhost") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], hreflang: "de", text: "blub"}}, | |||
rels: %{"me" => ["http://blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" hreflang=\"de\" href=\"http://blub\">blub</a>", "http://localhost") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], title: "blub", text: "blub"}}, | |||
rels: %{"me" => ["http://blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" title=\"blub\" href=\"http://blub\">blub</a>", "http://localhost") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], type: "text/html", text: "blub"}}, | |||
rels: %{"me" => ["http://blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" type=\"text/html\" href=\"http://blub\">blub</a>", "http://localhost") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{ | |||
"http://blub" => %{ | |||
rels: ["me"], | |||
media: "video", | |||
title: "blub", | |||
hreflang: "de", | |||
type: "text/html", | |||
text: "blub" | |||
} | |||
}, | |||
rels: %{"me" => ["http://blub"]} | |||
} = | |||
Microformats2.parse( | |||
"<a rel=\"me\" hreflang=\"de\" media=\"video\" title=\"blub\" type=\"text/html\" href=\"http://blub\">blub</a>", | |||
"http://localhost" | |||
) | |||
) | |||
end | |||
test "duplicate value doesn't overwrite the first one" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub", hreflang: "de"}}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse(""" | |||
<a rel="me" hreflang="de" href="http://blub">blub</a> | |||
<a rel="me" hreflang="en" href="http://blub">blah</a> | |||
""", | |||
"http://localhost")) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub", hreflang: "de"}}, | |||
rels: %{"me" => ["http://blub"]} | |||
} = | |||
Microformats2.parse( | |||
""" | |||
<a rel="me" hreflang="de" href="http://blub">blub</a> | |||
<a rel="me" hreflang="en" href="http://blub">blah</a> | |||
""", | |||
"http://localhost" | |||
) | |||
) | |||
end | |||
test "parse ignores template elements" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse(""" | |||
<a rel="me" href="http://blub">blub</a> | |||
<template><a rel="moo" href="http://blub">blub</a></template> | |||
""", | |||
"http://localhost")) | |||
assert( | |||
%{items: _, rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, rels: %{"me" => ["http://blub"]}} = | |||
Microformats2.parse( | |||
""" | |||
<a rel="me" href="http://blub">blub</a> | |||
<template><a rel="moo" href="http://blub">blub</a></template> | |||
""", | |||
"http://localhost" | |||
) | |||
) | |||
end | |||
test "parse generates an absolute URL" do | |||
assert(%{items: _, | |||
rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" href=\"/blub\">blub</a>", | |||
"http://localhost")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" href=\"blub\">blub</a>", | |||
"http://localhost")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://localhost/blah/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blah/blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" href=\"blub\">blub</a>", | |||
"http://localhost/blah/foo")) | |||
assert(%{items: _, | |||
rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blub"]}} = | |||
Microformats2.parse("<a rel=\"me\" href=\"/blub\">blub</a>", | |||
"http://localhost/blah/foo")) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" href=\"/blub\">blub</a>", "http://localhost") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" href=\"blub\">blub</a>", "http://localhost") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://localhost/blah/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blah/blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" href=\"blub\">blub</a>", "http://localhost/blah/foo") | |||
) | |||
assert( | |||
%{ | |||
items: _, | |||
rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, | |||
rels: %{"me" => ["http://localhost/blub"]} | |||
} = Microformats2.parse("<a rel=\"me\" href=\"/blub\">blub</a>", "http://localhost/blah/foo") | |||
) | |||
end | |||
end |