Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 730be3d268
Fetching contributors…

Cannot retrieve contributors at this time

file 125 lines (104 sloc) 3.655 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
-module(jorge).

-export([jorge/1]).

-ifdef(TEST).
-export([jorge_test/0]).
-endif.

-type key() :: atom() | binary().
-type value() :: key() | integer() | float() | fun(() -> iolist()).
-type attrs() :: [{key(), value()}].

-spec jorge(undefined) -> undefined;
           (Node :: {key(), value()}) -> iolist();
           (Node :: {key(), attrs(), value()}) -> iolist().
jorge(undefined) ->
   undefined;
jorge(Node) ->
    jorge_node(Node).

jorge_node({Key, Value}) ->
    jorge_node(jorge_key(Key), jorge_node(Value));
jorge_node({Key, Attrs, Value}) ->
    jorge_node(jorge_key(Key), jorge_attrs(Attrs), jorge_node(Value));
jorge_node(Value) ->
    jorge_value(Value).

jorge_node(Key, Value) ->
    [<<$<, Key/binary, $>>>, Value, <<"</", Key/binary, $>>>].

jorge_node(Key, Attrs, Value) ->
    [<<$<, Key/binary, Attrs/binary, $>>>, Value, <<"</", Key/binary, $>>>].

jorge_attrs(Attrs) ->
    jorge_attrs(Attrs, <<>>).

jorge_attrs([], Acc) ->
    Acc;
jorge_attrs([{Key, Value} | Rest], Acc) ->
    jorge_attrs(jorge_attr(jorge_key(Key), jorge_value(Value)), Rest, Acc).

jorge_attrs(Attr, Rest, Acc) ->
    jorge_attrs(Rest, <<Acc/binary, $\s, Attr/binary>>).

jorge_attr(Key, Value) ->
    <<Key/binary, "=\"", Value/binary, $">>.

jorge_key(Key) when is_atom(Key) ->
    atom_to_binary(Key, utf8);
jorge_key(Key) when is_binary(Key) ->
    Key.

jorge_value(Value) when is_binary(Value) ->
    Value;
jorge_value(Value) when is_list(Value) ->
    jorge_list(Value);
jorge_value(Value) when is_atom(Value) ->
    atom_to_binary(Value, utf8);
jorge_value(Value) when is_integer(Value) ->
    list_to_binary(integer_to_list(Value));
jorge_value(Value) when is_float(Value) ->
    list_to_binary(hd(io_lib:format("~p", [Value])));
jorge_value(Value) when is_function(Value, 0) ->
    jorge_value(Value()).

jorge_list(List) ->
    jorge_list(List, []).

jorge_list([], []) ->
    [];
jorge_list([], Acc) ->
    lists:reverse(Acc);
jorge_list([undefined | Rest], Acc) ->
    jorge_list(Rest, Acc);
jorge_list([List | Rest], Acc) when is_list(List) ->
    jorge_nested_list(List, Rest, Acc);
jorge_list([Head | Rest], Acc) ->
    jorge_list(Rest, [jorge_node(Head) | Acc]).

jorge_nested_list([], Siblings, Acc) ->
    jorge_list(Siblings, Acc);
jorge_nested_list([undefined | Rest], Siblings, Acc) ->
    jorge_nested_list(Rest, Siblings, Acc);
jorge_nested_list([Head | Rest], Siblings, Acc) ->
    jorge_nested_list(Rest, Siblings, [jorge_node(Head) | Acc]).

-ifdef(TEST).

jorge_test() ->
    Expected = [<<"<foo grault=\"garply\" waldo=\"fred\">">>,
                [<<"<bar>">>,
                 [[<<"<baz>">>,<<"2">>,<<"</baz>">>],
                  [<<"<quux>">>,<<"corge">>,<<"</quux>">>],
                  [<<"<plugh>">>,<<"5.0">>,<<"</plugh>">>],
                  [<<"<xyzzy>">>, <<"thud">>, <<"</xyzzy>">>],
                  [<<"<spam>">>, <<"eggs">>, <<"</spam>">>]],
                 <<"</bar>">>],
                <<"</foo>">>],
    Expected = jorge(
        {foo, [{grault, garply}, {waldo, fred}],
            {bar, [
                {baz, 2},
                {quux, corge},
                {plugh, 5.0},
                undefined,
                {xyzzy, <<"thud">>},
                {spam, fun() -> eggs end}
            ]}
        }
    ),
    
    Nested = [<<"<nested>">>,
                [[<<"<foo>">>, <<"bar">>, <<"</foo>">>],
                 [<<"<abc>">>, <<"123">>, <<"</abc>">>],
                 [<<"<def>">>, <<"456">>, <<"</def>">>]],
              <<"</nested>">>],
    
    Nested = jorge(
        {nested, [
            {foo, bar},
            [{abc, 123}, undefined, {def, 456}]
        ]}
    ).

-endif.
Something went wrong with that request. Please try again.