erlydtl_unparser.erl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. -module(erlydtl_unparser).
  2. -export([unparse/1, unparse/2]).
  3. unparse(DjangoParseTree, undefined) ->
  4. unparse(DjangoParseTree);
  5. unparse(DjangoParseTree, true) ->
  6. Text = unparse(DjangoParseTree),
  7. Trimmed = re:replace(Text, <<"(^\\s+)|(\\s+$)|\n">>, <<"">>, [global, multiline]),
  8. Joined = join_iolist(Trimmed, " "),
  9. binary_to_list(iolist_to_binary(Joined)).
  10. join_iolist(IOList, Sep) ->
  11. join_iolist(IOList, Sep, []).
  12. join_iolist([[]|IOList], Sep, Acc) ->
  13. join_iolist(IOList, Sep, Acc);
  14. join_iolist([Data|IOList], Sep, Acc) ->
  15. join_iolist(IOList, Sep, [Sep, Data|Acc]);
  16. join_iolist([], _, [_|Acc]) ->
  17. lists:reverse(Acc);
  18. join_iolist(IOList, _, Acc) ->
  19. lists:reverse([IOList|Acc]).
  20. unparse(DjangoParseTree) ->
  21. do_unparse(DjangoParseTree).
  22. do_unparse(DjangoParseTree) ->
  23. do_unparse(DjangoParseTree, []).
  24. do_unparse([], Acc) ->
  25. lists:flatten(lists:reverse(Acc));
  26. do_unparse([{'extends', Value}|Rest], Acc) ->
  27. do_unparse(Rest, [["{% extends ", unparse_value(Value), " %}"]|Acc]);
  28. do_unparse([{'autoescape', OnOrOff, Contents}|Rest], Acc) ->
  29. do_unparse(Rest, [["{% autoescape ", unparse_identifier(OnOrOff), " %}", do_unparse(Contents), "{% endautoescape %}"]|Acc]);
  30. do_unparse([{'block', Identifier, Contents}|Rest], Acc) ->
  31. do_unparse(Rest, [["{% block ", unparse_identifier(Identifier), " %}", do_unparse(Contents), "{% endblock %}"]|Acc]);
  32. do_unparse([{'blocktrans', Args, Contents, undefined}|Rest], Acc) ->
  33. do_unparse(Rest, [["{% blocktrans ", unparse_blocktrans_args(Args), " %}", do_unparse(Contents), "{% endblocktrans %}"]|Acc]);
  34. do_unparse([{'blocktrans', Args, Contents, PluralContents}|Rest], Acc) ->
  35. do_unparse(Rest, [["{% blocktrans ", unparse_blocktrans_args(Args), " %}",
  36. do_unparse(Contents),
  37. "{% plural %}",
  38. do_unparse(PluralContents),
  39. "{% endblocktrans %}"]|Acc]);
  40. do_unparse([{'call', Identifier}|Rest], Acc) ->
  41. do_unparse(Rest, [["{% call ", unparse_identifier(Identifier), " %}"]|Acc]);
  42. do_unparse([{'call', Identifier, With}|Rest], Acc) ->
  43. do_unparse(Rest, [["{% call ", unparse_identifier(Identifier), " with ", unparse_args(With), " %}"]|Acc]);
  44. do_unparse([{'comment', Contents}|Rest], Acc) ->
  45. do_unparse(Rest, [["{% comment %}", do_unparse(Contents), "{% endcomment %}"]|Acc]);
  46. do_unparse([{'comment_tag', _Pos, Text}|Rest], Acc) ->
  47. do_unparse(Rest, [["{#", Text, "#}"]|Acc]);
  48. do_unparse([{'cycle', Names}|Rest], Acc) ->
  49. do_unparse(Rest, [["{% cycle ", do_unparse(Names), " %}"]|Acc]);
  50. do_unparse([{'cycle_compat', Names}|Rest], Acc) ->
  51. do_unparse(Rest, [["{% cycle ", unparse_cycle_compat_names(Names), " %}"]|Acc]);
  52. do_unparse([{'date', 'now', Value}|Rest], Acc) ->
  53. do_unparse(Rest, [["{% now ", unparse_value(Value), " %}"]|Acc]);
  54. do_unparse([{'filter', FilterList, Contents}|Rest], Acc) ->
  55. do_unparse(Rest, [["{% filter ", unparse_filters(FilterList), " %}", do_unparse(Contents), "{% endfilter %}"]|Acc]);
  56. do_unparse([{'firstof', Vars}|Rest], Acc) ->
  57. do_unparse(Rest, [["{% firstof ", do_unparse(Vars), " %}"]|Acc]);
  58. do_unparse([{'for', {'in', IteratorList, Identifier}, Contents}|Rest], Acc) ->
  59. do_unparse(Rest, [["{% for ", unparse_identifier(Identifier), " in ", do_unparse(IteratorList), " %}",
  60. do_unparse(Contents),
  61. "{% endfor %}"]|Acc]);
  62. do_unparse([{'for', {'in', IteratorList, Identifier}, Contents, EmptyPartsContents}|Rest], Acc) ->
  63. do_unparse(Rest, [["{% for ", unparse_identifier(Identifier), " in ", do_unparse(IteratorList), " %}",
  64. do_unparse(Contents),
  65. "{% empty %}",
  66. do_unparse(EmptyPartsContents),
  67. "{% endfor %}"]|Acc]);
  68. do_unparse([{'if', Expression, Contents}|Rest], Acc) ->
  69. do_unparse(Rest, [["{% if ", unparse_expression(Expression), " %}",
  70. do_unparse(Contents),
  71. "{% endif %}"]|Acc]);
  72. do_unparse([{'ifchanged', Expression, IfContents}|Rest], Acc) ->
  73. do_unparse(Rest, [["{% ifchanged ", unparse_expression(Expression), " %}",
  74. do_unparse(IfContents),
  75. "{% endifchanged %}"]|Acc]);
  76. do_unparse([{'ifchangedelse', Expression, IfContents, ElseContents}|Rest], Acc) ->
  77. do_unparse(Rest, [["{% ifchanged ", unparse_expression(Expression), " %}",
  78. do_unparse(IfContents),
  79. "{% else %}",
  80. do_unparse(ElseContents),
  81. "{% endifchanged %}"]|Acc]);
  82. do_unparse([{'ifelse', Expression, IfContents, ElseContents}|Rest], Acc) ->
  83. do_unparse(Rest, [["{% if ", unparse_expression(Expression), " %}",
  84. do_unparse(IfContents),
  85. "{% else %}",
  86. do_unparse(ElseContents),
  87. "{% endif %}"]|Acc]);
  88. do_unparse([{'ifequal', [Arg1, Arg2], Contents}|Rest], Acc) ->
  89. do_unparse(Rest, [["{% ifequal ", unparse_value(Arg1), " ", unparse_value(Arg2), " %}",
  90. do_unparse(Contents),
  91. "{% endifequal %}"]|Acc]);
  92. do_unparse([{'ifequalelse', [Arg1, Arg2], IfContents, ElseContents}|Rest], Acc) ->
  93. do_unparse(Rest, [["{% ifequal ", unparse_value(Arg1), " ", unparse_value(Arg2), " %}",
  94. do_unparse(IfContents),
  95. "{% else %}",
  96. do_unparse(ElseContents),
  97. "{% endifequal %}"]|Acc]);
  98. do_unparse([{'ifnotequal', [Arg1, Arg2], Contents}|Rest], Acc) ->
  99. do_unparse(Rest, [["{% ifnotequal ", unparse_value(Arg1), " ", unparse_value(Arg2), " %}",
  100. do_unparse(Contents),
  101. "{% endifnotequal %}"]|Acc]);
  102. do_unparse([{'ifnotequalelse', [Arg1, Arg2], IfContents, ElseContents}|Rest], Acc) ->
  103. do_unparse(Rest, [["{% ifnotequal ", unparse_value(Arg1), " ", unparse_value(Arg2), " %}",
  104. do_unparse(IfContents),
  105. "{% else %}",
  106. do_unparse(ElseContents),
  107. "{% endifnotequal %}"]|Acc]);
  108. do_unparse([{'include', Value, []}|Rest], Acc) ->
  109. do_unparse(Rest, [["{% include ", unparse_value(Value), " %}"]|Acc]);
  110. do_unparse([{'include', Value, Args}|Rest], Acc) ->
  111. do_unparse(Rest, [["{% include ", unparse_value(Value), " with ", unparse_args(Args)]|Acc]);
  112. do_unparse([{'include_only', Value, []}|Rest], Acc) ->
  113. do_unparse(Rest, [["{% include ", unparse_value(Value), " only %}"]|Acc]);
  114. do_unparse([{'include_only', Value, Args}|Rest], Acc) ->
  115. do_unparse(Rest, [["{% include ", unparse_value(Value), " with ", unparse_args(Args), " only %}"]|Acc]);
  116. do_unparse([{'regroup', {Variable, Identifier1, Identifier2}, Contents}|Rest], Acc) ->
  117. do_unparse(Rest, [["{% regroup ", unparse_value(Variable), " by ", unparse_identifier(Identifier1), " as ", unparse_identifier(Identifier2), " %}",
  118. do_unparse(Contents),
  119. "{% endregroup %}"]|Acc]);
  120. do_unparse([{'spaceless', Contents}|Rest], Acc) ->
  121. do_unparse(Rest, [["{% spaceless %}", do_unparse(Contents), "{% endspaceless %}"]|Acc]);
  122. do_unparse([{'ssi', Arg}|Rest], Acc) ->
  123. do_unparse(Rest, [["{% ssi ", unparse_value(Arg), " %}"]|Acc]);
  124. do_unparse([{'ssi_parsed', Arg}|Rest], Acc) ->
  125. do_unparse(Rest, [["{% ssi ", unparse_value(Arg), " parsed %}"]|Acc]);
  126. do_unparse([{'string', _, String}|Rest], Acc) ->
  127. do_unparse(Rest, [[String]|Acc]);
  128. do_unparse([{'tag', Identifier, []}|Rest], Acc) ->
  129. do_unparse(Rest, [["{% ", unparse_identifier(Identifier), " %}"]|Acc]);
  130. do_unparse([{'tag', Identifier, Args}|Rest], Acc) ->
  131. do_unparse(Rest, [["{% ", unparse_identifier(Identifier), " ", unparse_args(Args), " %}"]|Acc]);
  132. do_unparse([{'templatetag', Identifier}|Rest], Acc) ->
  133. do_unparse(Rest, [["{% templatetag ", unparse_identifier(Identifier), " %}"]|Acc]);
  134. do_unparse([{'trans', Value}|Rest], Acc) ->
  135. do_unparse(Rest, [["{% trans ", unparse_value(Value), " %}"]|Acc]);
  136. do_unparse([{'widthratio', Numerator, Denominator, Scale}|Rest], Acc) ->
  137. do_unparse(Rest, [["{% widthratio ", unparse_value(Numerator), " ", unparse_value(Denominator), " ", unparse_value(Scale), " %}"]|Acc]);
  138. do_unparse([{'with', Args, Contents}|Rest], Acc) ->
  139. do_unparse(Rest, [["{% with ", unparse_args(Args), " %}",
  140. do_unparse(Contents),
  141. "{% endwidth %}"]|Acc]);
  142. do_unparse([ValueToken|Rest], Acc) ->
  143. do_unparse(Rest, [["{{ ", unparse_value(ValueToken), " }}"]|Acc]).
  144. unparse_identifier({identifier, _, Name}) ->
  145. atom_to_list(Name).
  146. unparse_filters(FilterList) ->
  147. unparse_filters(FilterList, []).
  148. unparse_filters([], Acc) ->
  149. lists:reverse(Acc);
  150. unparse_filters([Filter], Acc) ->
  151. unparse_filters([], [unparse_filter(Filter)|Acc]);
  152. unparse_filters([Filter|Rest], Acc) ->
  153. unparse_filters(Rest, lists:reverse([unparse_filter(Filter), "|"], Acc)).
  154. unparse_filter([Identifier]) ->
  155. unparse_identifier(Identifier);
  156. unparse_filter([Identifier, Arg]) ->
  157. [unparse_identifier(Identifier), ":", unparse_value(Arg)].
  158. unparse_expression({'expr', "in", Arg1, Arg2}) ->
  159. [unparse_value(Arg1), " in ", unparse_value(Arg2)];
  160. unparse_expression({'expr', "not", {'expr', "in", Arg1, Arg2}}) ->
  161. [unparse_value(Arg1), " not in ", unparse_value(Arg2)];
  162. unparse_expression({'expr', "not", Expr}) ->
  163. ["not ", unparse_expression(Expr)];
  164. unparse_expression({'expr', "eq", Arg1, Arg2}) ->
  165. [unparse_value(Arg1), " == ", unparse_value(Arg2)];
  166. unparse_expression({'expr', "ne", Arg1, Arg2}) ->
  167. [unparse_value(Arg1), " != ", unparse_value(Arg2)];
  168. unparse_expression({'expr', "ge", Arg1, Arg2}) ->
  169. [unparse_value(Arg1), " >= ", unparse_value(Arg2)];
  170. unparse_expression({'expr', "le", Arg1, Arg2}) ->
  171. [unparse_value(Arg1), " <= ", unparse_value(Arg2)];
  172. unparse_expression({'expr', "gt", Arg1, Arg2}) ->
  173. [unparse_value(Arg1), " > ", unparse_value(Arg2)];
  174. unparse_expression({'expr', "lt", Arg1, Arg2}) ->
  175. [unparse_value(Arg1), " < ", unparse_value(Arg2)];
  176. unparse_expression({'expr', "or", Arg1, Arg2}) ->
  177. [unparse_expression(Arg1), " or ", unparse_expression(Arg2)];
  178. unparse_expression({'expr', "and", Arg1, Arg2}) ->
  179. [unparse_expression(Arg1), " and ", unparse_expression(Arg2)];
  180. unparse_expression(Other) ->
  181. unparse_value(Other).
  182. unparse_value({'string_literal', _, Value}) ->
  183. Value;
  184. unparse_value({'number_literal', _, Value}) ->
  185. Value;
  186. unparse_value({'apply_filter', Variable, Filter}) ->
  187. [unparse_value(Variable), "|", unparse_filter(Filter)];
  188. unparse_value({'attribute', {Variable, Identifier}}) ->
  189. [unparse_value(Variable), ".", unparse_identifier(Identifier)];
  190. unparse_value({'variable', Identifier}) ->
  191. unparse_identifier(Identifier).
  192. unparse_args(Args) ->
  193. unparse_args(Args, []).
  194. unparse_args([], Acc) ->
  195. collect_args_acc(Acc);
  196. unparse_args([{{identifier, _, Name}, Value}|Args], Acc) ->
  197. unparse_args(Args, [[atom_to_list(Name), "=", unparse_value(Value)]|Acc]).
  198. unparse_cycle_compat_names(Names) ->
  199. unparse_cycle_compat_names(Names, []).
  200. unparse_cycle_compat_names([], Acc) ->
  201. lists:reverse(Acc);
  202. unparse_cycle_compat_names([{identifier, _, Name}], Acc) ->
  203. unparse_cycle_compat_names([], [atom_to_list(Name)|Acc]);
  204. unparse_cycle_compat_names([{identifier, _, Name}|Rest], Acc) ->
  205. unparse_cycle_compat_names(Rest, lists:reverse([atom_to_list(Name), ", "], Acc)).
  206. unparse_blocktrans_args(Args) ->
  207. unparse_blocktrans_args(Args, []).
  208. unparse_blocktrans_args([], Acc) ->
  209. collect_args_acc(Acc);
  210. unparse_blocktrans_args([{args, WithArgs}|Args], Acc) ->
  211. unparse_blocktrans_args(
  212. Args, [["with ", unparse_args(WithArgs)]|Acc]);
  213. unparse_blocktrans_args([{count, Count}|Args], Acc) ->
  214. unparse_blocktrans_args(
  215. Args, [["count ", unparse_args([Count])]|Acc]);
  216. unparse_blocktrans_args([{context, Context}|Args], Acc) ->
  217. unparse_blocktrans_args(
  218. Args, [["context ", unparse_value(Context)]|Acc]);
  219. unparse_blocktrans_args([trimmed|Args], Acc) ->
  220. unparse_blocktrans_args(
  221. Args, ["trimmed"|Acc]).
  222. collect_args_acc(Acc) ->
  223. lists:flatten(string:join(lists:reverse(Acc), " ")).