defmodule Outlook.InternalTree.InternalTree do alias Outlook.InternalTree.{InternalNode,TranslationUnit} def garnish([%TranslationUnit{} = node | rest], options) do [ set_attributes(node, options.tunits, options.tu_ids) | garnish(rest, options) ] end def garnish([%InternalNode{type: :element} = node | rest], options) do node = set_attributes(node, options.elements, options.el_ids, options.el_names) [ %InternalNode{node | content: garnish(node.content, options) } | garnish(rest, options) ] end def garnish([node | rest], options) do [ node | garnish(rest, options) ] end def garnish([], _), do: [] defp set_attributes(node, atts, ids, []) do set_attributes(node, atts, ids) end defp set_attributes(node, atts, ids, names) do if node.name in names do set_attributes(node, atts, []) else set_attributes(node, atts, ids) end end defp set_attributes(node, atts, []) do set_attributes(node, atts) end defp set_attributes(node, atts, ids) do if node.nid in ids do set_attributes(node, atts) else node end end defp set_attributes(node, atts) do node_atts = Map.get(node, :attributes, %{}) |> Map.merge(Map.get(node.eph, :attributes, %{})) attributes = Enum.map(atts, fn {k,v} -> nv = case is_function(v) do true -> v.(node) false -> v end {k,nv} end) |> Enum.into(node_atts) %{node | eph: Map.put(node.eph, :attributes, attributes)} end def collect_tunit_ids([%TranslationUnit{} = node | rest]) do [node.nid | collect_tunit_ids(rest)] end def collect_tunit_ids([%{type: :element} = node | rest]) do collect_tunit_ids(node.content) ++ collect_tunit_ids(rest) end def collect_tunit_ids([node | rest]) do collect_tunit_ids(rest) end def collect_tunit_ids([]), do: [] end