anchor.diff:  
   
   %% @doc Escape all properties used for an update statement. Only leaves the body property intact.
  --spec escape_props(list()) -> list().
  +-spec escape_props(list() | map()) -> list() | map().
   escape_props(Props) ->
       escape_props(Props, []).
   
  --spec escape_props(list(), Options::list()) -> list().
  -escape_props(Props, Options) ->
  -    [ escape_props1(P, Options) || P <- Props ].
  -
  -escape_props1({_K,V} = Prop, _Options) when is_float(V); is_integer(V); is_atom(V) -> 
  -    Prop;
  -escape_props1({body, V}, Options) ->
  -    {body, sanitize(V, Options)};
  -escape_props1({body_extra, V}, Options) ->
  -    {body_extra, sanitize(V, Options)};
  -escape_props1({summary, Summary}, _Options) ->
  -    {summary, nl2br(escape_value(Summary))};
  -escape_props1({blocks, V}, Options) when is_list(V) ->
  -    V1 = [ escape_props(L, Options) || L <- V ],
  -    {blocks, V1};
  -escape_props1({website, V}, _Options) ->
  -    V1 = escape_value(sanitize_uri(V)),
  -    {website, V1};
  -escape_props1({K, V}, Options) ->
  -    case z_convert:to_list(K) of
  -        "is_" ++ _ ->
  -            {K, z_convert:to_bool(V)};
  -        KS ->
  -            EscapeFun = case lists:reverse(KS) of
  -                            "lmth_" ++ _ -> fun(A) -> sanitize(A, Options) end; %% prop ends in '_html'
  -                            "iru_" ++ _ -> fun(A) -> escape_value(sanitize_uri(A)) end; %% prop ends in '_uri'
  -                            "lru_" ++ _ -> fun(A) -> escape_value(sanitize_uri(A)) end; %% prop ends in '_url'
  -                            _ -> fun escape_value/1
  -                        end,
  -            {K, EscapeFun(V)}
  -    end;
  -escape_props1(P, _Options) ->
  -    P.
  +-spec escape_props(list() | map(), Options::list()) -> list() | map().
  +escape_props(Props, Options) when is_list(Props) ->
  +    lists:map(
  +        fun({P, V}) ->
  +            V1 = escape_props1(z_convert:to_binary(P), V, Options),
  +            {P, V1}
  +        end,
  +        Props);
  +escape_props(Props, Options) when is_map(Props) ->
  +    maps:map(
  +        fun(K, V) ->
  +            escape_props1(z_convert:to_binary(K), V, Options)
  +        end,
  +        Props).
  +
  +escape_props1(_K, V, _Options) when is_float(V); is_integer(V); is_atom(V) ->
  +    V;
  +escape_props1(<<"body", _/binary>>, V, Options) ->
  +    sanitize(V, Options);
  +escape_props1(<<"summary">>, Summary, _Options) ->
  +    nl2br(escape_value(Summary));
  +escape_props1(<<"blocks">>, V, Options) when is_list(V) ->
  +    [ escape_props(L, Options) || L <- V ];
  +escape_props1(<<"website">>, V, _Options) ->
  +    escape_value(sanitize_uri(V));
  +escape_props1(<<"is_", _/binary>>, V, _Options) ->
  +    z_convert:to_bool(V);
  +escape_props1(_K, V, Options) when is_map(V) ->
  +    escape_props(V, Options);
  +escape_props1(K, V, Options) ->
  +    Type = lists:last(binary:split(K, <<"_">>, [global])),
  +    case Type of
  +        <<"html">> -> sanitize(V, Options);
  +        <<"uri">> -> escape_value(sanitize_uri(V));
  +        <<"url">> -> escape_value(sanitize_uri(V));
  +        _ -> escape_value(V)
  +    end.
   
   escape_value({trans, _Ts} = Tr) ->
       escape(Tr);
  
positive.code: -spec escape(list()|binary()|{trans, list()}) -> binary() | undefined.
  escape({trans, Tr}) ->
      {trans, [{Lang, escape(V)} || {Lang,V} <- Tr]};
  escape(undefined) -> 
      undefined;
  escape(<<>>) -> 
      <<>>;
  escape([]) ->
      <<>>;
  
negative.code: -spec escape_check(list()|binary()|{trans, list()}) -> binary() | undefined.
  escape_check({trans, Tr}) ->
      {trans, [{Lang, escape_check(V)} || {Lang,V} <- Tr]};
  escape_check(undefined) ->
      undefined;
  escape_check(<<>>) ->
      <<>>;
  escape_check([]) ->
      <<>>;
  