From 6481ebc506cedb6d75f1eb820f29308060120a0c Mon Sep 17 00:00:00 2001 From: Christian Kruse Date: Mon, 5 Feb 2018 10:17:44 +0100 Subject: [PATCH] mix format --- .formatter.exs | 5 + lib/implied.ex | 144 ++++++++++------- lib/items.ex | 154 +++++++++++------- lib/microformats2.ex | 44 ++--- lib/rels.ex | 67 ++++---- mix.exs | 32 ++-- test/items_test.exs | 377 ++++++++++++++++++++++++++++--------------- test/rels_test.exs | 256 +++++++++++++++++------------ 8 files changed, 645 insertions(+), 434 deletions(-) create mode 100644 .formatter.exs diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..cbe0d23 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,5 @@ +[ + inputs: ["lib/**/*.{ex,exs}", "mix.exs", "config/*.exs", "test/**/*.{ex,exs}"], + line_length: 120, + rename_deprecated_at: "1.4.5" +] diff --git a/lib/implied.ex b/lib/implied.ex index d71c9ef..e841cf9 100644 --- a/lib/implied.ex +++ b/lib/implied.ex @@ -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 diff --git a/lib/items.ex b/lib/items.ex index 060925e..0d4ccee 100644 --- a/lib/items.ex +++ b/lib/items.ex @@ -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 diff --git a/lib/microformats2.ex b/lib/microformats2.ex index 50f4bc4..2d73ec8 100644 --- a/lib/microformats2.ex +++ b/lib/microformats2.ex @@ -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 || "/")) diff --git a/lib/rels.ex b/lib/rels.ex index 2bb8fb4..2fbc13e 100644 --- a/lib/rels.ex +++ b/lib/rels.ex @@ -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 diff --git a/mix.exs b/mix.exs index 7259748..22cb6c7 100644 --- a/mix.exs +++ b/mix.exs @@ -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 diff --git a/test/items_test.exs b/test/items_test.exs index ba60c62..0ffe439 100644 --- a/test/items_test.exs +++ b/test/items_test.exs @@ -4,169 +4,280 @@ defmodule Microformats2ItemsTest do test "successfully parses a whole document" do str = """ - - - - Blub - - -

Blah

-
- Luke lulu - blah -
- - -""" + + + + Blub + + +

Blah

+
+ Luke lulu + blah +
+ + + """ 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("Frances Berriman", - "http://localhost") - - assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ - name: ["Ben Ward"], - url: ["http://benward.me"]}}]} = - Microformats2.parse("Ben Ward", - "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(""" - - Rohit Khare - -""", - "http://localhost") + assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{name: ["Frances Berriman"]}}]} = + Microformats2.parse("Frances Berriman", "http://localhost") + + assert %{ + rels: _, + rel_urls: _, + items: [%{type: ["h-card"], properties: %{name: ["Ben Ward"], url: ["http://benward.me"]}}] + } = Microformats2.parse("Ben Ward", "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( + """ + + Rohit Khare + + """, + "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("
Ben Ward
", - "http://benward.me") - - assert %{rels: _, rel_urls: _, items: [%{type: ["h-card"], properties: %{ - name: ["Ben Ward"], - url: ["http://benward.me/foo"]}}]} = - Microformats2.parse("
Ben Ward
", - "http://benward.me") + assert %{ + rels: _, + rel_urls: _, + items: [%{type: ["h-card"], properties: %{name: ["Ben Ward"], url: ["http://benward.me/foo"]}}] + } = + Microformats2.parse( + "
Ben Ward
", + "http://benward.me" + ) + + assert %{ + rels: _, + rel_urls: _, + items: [%{type: ["h-card"], properties: %{name: ["Ben Ward"], url: ["http://benward.me/foo"]}}] + } = Microformats2.parse("
Ben Ward
", "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: "

He's right, you know?

", - 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: "

He's right, you know?

", 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 diff --git a/test/rels_test.exs b/test/rels_test.exs index f088f94..ce33fea 100644 --- a/test/rels_test.exs +++ b/test/rels_test.exs @@ -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("blub", - "http://localhost")) + assert( + %{items: _, rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, rels: %{"me" => ["http://blub"]}} = + Microformats2.parse("blub", "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(""" -blub -blub -""", - "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( + """ + blub + blub + """, + "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(""" -blub -blub -""", - "http://localhost")) + assert( + %{items: _, rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, rels: %{"me" => ["http://blub"]}} = + Microformats2.parse( + """ + blub + blub + """, + "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(""" -blub -blub -""", - "http://localhost")) + assert( + %{ + items: _, + rel_urls: %{"http://blub" => %{rels: ["me", "moo"], text: "blub"}}, + rels: %{"me" => ["http://blub"], "moo" => ["http://blub"]} + } = + Microformats2.parse( + """ + blub + blub + """, + "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("blub", - "http://localhost")) - - assert(%{items: _, - rel_urls: %{"http://blub" => %{ rels: ["me"], hreflang: "de", text: "blub" }}, - rels: %{"me" => ["http://blub"]}} = - Microformats2.parse("blub", - "http://localhost")) - - assert(%{items: _, - rel_urls: %{"http://blub" => %{ rels: ["me"], title: "blub", text: "blub" }}, - rels: %{"me" => ["http://blub"]}} = - Microformats2.parse("blub", - "http://localhost")) - - assert(%{items: _, - rel_urls: %{"http://blub" => %{ rels: ["me"], type: "text/html", text: "blub" }}, - rels: %{"me" => ["http://blub"]}} = - Microformats2.parse("blub", - "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("blub", - "http://localhost")) + assert( + %{ + items: _, + rel_urls: %{"http://blub" => %{rels: ["me"], media: "video", text: "blub"}}, + rels: %{"me" => ["http://blub"]} + } = Microformats2.parse("blub", "http://localhost") + ) + + assert( + %{ + items: _, + rel_urls: %{"http://blub" => %{rels: ["me"], hreflang: "de", text: "blub"}}, + rels: %{"me" => ["http://blub"]} + } = Microformats2.parse("blub", "http://localhost") + ) + + assert( + %{ + items: _, + rel_urls: %{"http://blub" => %{rels: ["me"], title: "blub", text: "blub"}}, + rels: %{"me" => ["http://blub"]} + } = Microformats2.parse("blub", "http://localhost") + ) + + assert( + %{ + items: _, + rel_urls: %{"http://blub" => %{rels: ["me"], type: "text/html", text: "blub"}}, + rels: %{"me" => ["http://blub"]} + } = Microformats2.parse("blub", "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( + "blub", + "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(""" -blub -blah -""", - "http://localhost")) - + assert( + %{ + items: _, + rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub", hreflang: "de"}}, + rels: %{"me" => ["http://blub"]} + } = + Microformats2.parse( + """ + blub + blah + """, + "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(""" -blub - -""", - "http://localhost")) + assert( + %{items: _, rel_urls: %{"http://blub" => %{rels: ["me"], text: "blub"}}, rels: %{"me" => ["http://blub"]}} = + Microformats2.parse( + """ + blub + + """, + "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("blub", - "http://localhost")) - - assert(%{items: _, - rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, - rels: %{"me" => ["http://localhost/blub"]}} = - Microformats2.parse("blub", - "http://localhost")) - - assert(%{items: _, - rel_urls: %{"http://localhost/blah/blub" => %{rels: ["me"], text: "blub"}}, - rels: %{"me" => ["http://localhost/blah/blub"]}} = - Microformats2.parse("blub", - "http://localhost/blah/foo")) - - assert(%{items: _, - rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, - rels: %{"me" => ["http://localhost/blub"]}} = - Microformats2.parse("blub", - "http://localhost/blah/foo")) - + assert( + %{ + items: _, + rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, + rels: %{"me" => ["http://localhost/blub"]} + } = Microformats2.parse("blub", "http://localhost") + ) + + assert( + %{ + items: _, + rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, + rels: %{"me" => ["http://localhost/blub"]} + } = Microformats2.parse("blub", "http://localhost") + ) + + assert( + %{ + items: _, + rel_urls: %{"http://localhost/blah/blub" => %{rels: ["me"], text: "blub"}}, + rels: %{"me" => ["http://localhost/blah/blub"]} + } = Microformats2.parse("blub", "http://localhost/blah/foo") + ) + + assert( + %{ + items: _, + rel_urls: %{"http://localhost/blub" => %{rels: ["me"], text: "blub"}}, + rels: %{"me" => ["http://localhost/blub"]} + } = Microformats2.parse("blub", "http://localhost/blah/foo") + ) end - end