|
- 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)
- 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()
-
- if Microformats2.blank?(url) do
- entry
- else
- Map.put(entry, :properties, Map.put(entry[:properties], :url, [Microformats2.abs_uri(url, doc_url, doc)]))
- end
- else
- entry
- end
- end
-
- defp implied_photo_property(entry, root) 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()
-
- if Microformats2.blank?(url) do
- entry
- else
- Map.put(entry, :properties, Map.put(entry[:properties], :photo, [url]))
- end
- else
- entry
- 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()
-
- Map.put(entry, :properties, Map.put(entry[:properties], :name, [nam]))
- else
- entry
- end
- end
-
- defp implied_name_deep({_, _, children}) do
- 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)
- {_, _, sec_node_children} = sec_node
- 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)
-
- if Enum.count(sec_only_nodes) == 1 do
- third_node = sec_only_nodes |> List.first()
- implied_name_attrval(third_node)
- end
- else
- attrval
- end
- end
- end
-
- defp implied_name_attrval(node = {"img", _, _}) do
- Floki.attribute(node, "alt") |> List.first()
- end
-
- defp implied_name_attrval(node = {"area", _, _}) do
- Floki.attribute(node, "alt") |> List.first()
- end
-
- defp implied_name_attrval(node = {"abbr", _, _}) do
- 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()
-
- Enum.count(objects) == 1 ->
- 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)
-
- if Enum.count(only_nodes) == 1 do
- child = List.first(children)
- sec_imgs = direct_not_h_children_with_attr(child, "img", "src")
- sec_objs = direct_not_h_children_with_attr(child, "object", "data")
-
- cond do
- Enum.count(sec_imgs) == 1 ->
- List.first(sec_imgs) |> Floki.attribute("src") |> List.first()
-
- Enum.count(sec_objs) == 1 ->
- List.first(sec_objs) |> Floki.attribute("data") |> List.first()
-
- true ->
- nil
- end
- else
- nil
- end
- end
- end
-
- defp implied_url_deep(root) do
- as = direct_not_h_children_with_attr(root, "a", "href")
- areas = direct_not_h_children_with_attr(root, "area", "href")
-
- cond do
- Enum.count(as) == 1 ->
- List.first(as) |> Floki.attribute("href") |> List.first()
-
- Enum.count(areas) == 1 ->
- 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()
- end
-
- defp implied_photo_attrval(node = {"object", _, _}) do
- 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)
- end
-
- defp implied_url_attrval(node = {"a", _, _}) do
- Floki.attribute(node, "href") |> List.first()
- end
-
- defp implied_url_attrval(node = {"area", _, _}) do
- Floki.attribute(node, "href") |> List.first()
- end
-
- defp implied_url_attrval(_) do
- nil
- end
- end
|