Browse Source

Adding support for "Assignment tags" (https://docs.djangoproject.com/en/1.6/howto/custom-template-tags/)
example: {% custom_tag as var_tag %}{{ var_tag }} more {{ var_tag }}

sag 10 years ago
parent
commit
913fa69e8b

+ 58 - 0
src/erlydtl_beam_compiler.erl

@@ -686,6 +686,8 @@ body_ast(DjangoParseTree, BodyScope, TreeWalker) ->
                 string_ast(String, TW);
             ({'tag', Name, Args}, TW) ->
                 tag_ast(Name, Args, TW);
+            ({'tag', Name, Args, {identifier, _, NewTagVar}}, TW) ->
+                tag_ast(Name, Args, NewTagVar, TW);
             ({'templatetag', {_, _, TagName}}, TW) ->
                 templatetag_ast(TagName, TW);
             ({'trans', Value}, TW) ->
@@ -1552,6 +1554,62 @@ custom_tags_modules_ast({identifier, Pos, Name}, InterpretedArgs,
             end
     end.
 
+tag_ast(Name, Args, NewTagVar, TreeWalker) ->
+    {{InterpretedArgs, AstInfo1}, TreeWalker1} = interpret_args(Args, TreeWalker),
+    {{RenderAst, RenderInfo}, TreeWalker2} = custom_tags_modules_ast(Name, InterpretedArgs, NewTagVar, TreeWalker1),
+    {{RenderAst, merge_info(AstInfo1, RenderInfo)}, TreeWalker2}.
+
+custom_tags_modules_ast({identifier, Pos, Name}, InterpretedArgs, NewTagVar,
+                        #treewalker{
+                           context=#dtl_context{
+                                      tags = Tags,
+                                      module = Module,
+                                      is_compiling_dir=IsCompilingDir
+                                     }
+                          }=TreeWalker) ->
+  LocalVarAst = varname_ast(NewTagVar),
+    case proplists:get_value(Name, Tags) of
+        {Mod, Fun}=Tag ->
+            case lists:max([-1] ++ [I || {N,I} <- Mod:module_info(exports), N =:= Fun]) of
+                2 ->
+                      {Id, TreeWalker1} = begin_scope(
+                        {[{NewTagVar, LocalVarAst}],
+                          [?Q("_@LocalVarAst = '@Mod@':'@Fun@'([_@InterpretedArgs], RenderOptions)")]},
+                        TreeWalker
+                      ),
+                  {{Id, #ast_info{}}, TreeWalker1};
+                1 ->
+                      {Id, TreeWalker1} = begin_scope(
+                        {[{NewTagVar, LocalVarAst}],
+                          [?Q("_@LocalVarAst = '@Mod@':'@Fun@'([_@InterpretedArgs])")]},
+                        TreeWalker
+                  ),
+                  {{Id, #ast_info{}}, TreeWalker1};
+
+                -1 ->
+                    empty_ast(?WARN({Pos, {missing_tag, Name, Tag}}, TreeWalker));
+                I ->
+                    empty_ast(?WARN({Pos, {bad_tag, Name, Tag, I}}, TreeWalker))
+            end;
+        undefined ->
+            if IsCompilingDir =/= false ->
+                      {Id, TreeWalker1} = begin_scope(
+                        {[{NewTagVar, LocalVarAst}],
+                          [?Q("_@LocalVarAst = '@Module@':'@Name@'([_@InterpretedArgs], RenderOptions)")]},
+                        TreeWalker
+                      ),
+                      {{Id, #ast_info{ custom_tags = [Name]}}, TreeWalker1};
+               true ->
+                     {Id, TreeWalker1} = begin_scope(
+                       {[{NewTagVar, LocalVarAst}],
+                         [?Q("_@LocalVarAst = '@Module@':'@Name@'([_@InterpretedArgs], RenderOptions)")]},
+                       TreeWalker
+                     ),
+                     {{Id, #ast_info{ custom_tags = [Name]}}, TreeWalker1}
+
+            end
+    end.
+
 call_ast(Module, TreeWalker) ->
     call_ast(Module, merl:var("_Variables"), #ast_info{}, TreeWalker).
 

+ 1 - 0
src/erlydtl_parser.yrl

@@ -447,6 +447,7 @@ WithBraced -> open_tag with_keyword Args close_tag : '$3'.
 EndWithBraced -> open_tag endwith_keyword close_tag.
 
 CustomTag -> open_tag identifier CustomArgs close_tag : {tag, '$2', '$3'}.
+CustomTag -> open_tag identifier CustomArgs as_keyword identifier close_tag : {tag, '$2', '$3', '$5'}.
 
 CustomArgs -> '$empty' : [].
 CustomArgs -> identifier '=' Value CustomArgs : [{'$1', '$3'}|'$4'].

+ 4 - 1
test/erlydtl_custom_tags.erl

@@ -1,6 +1,6 @@
 -module(erlydtl_custom_tags).
 
--export([custom1/1, custom2/2, custom3/2, custom4/1]).
+-export([custom1/1, custom2/2, custom3/2, custom4/1, custom1_var/2]).
 
 custom1(_TagVars = []) ->
     <<"b1">>.
@@ -13,3 +13,6 @@ custom3([], _RenderOptions = [{locale, ru}]) ->
 
 custom4(_TagVars = [<<"a">>]) ->
     <<"a">>.
+
+custom1_var(_TagVars = [], _O) ->
+[{name, <<"b1">>}, {count, 11}].

+ 11 - 0
test/erlydtl_custom_tags_lib.erl

@@ -0,0 +1,11 @@
+-module(erlydtl_custom_tags_lib).
+-behaviour(erlydtl_library).
+
+-export([version/0, inventory/1, customtag2_var/2]).
+
+version() -> 1.
+
+inventory(filters) -> [];
+inventory(tags) -> [customtag2_var].
+
+customtag2_var(_V,_R) -> [{name, <<"b1">>}, {count, 11}].

+ 8 - 1
test/erlydtl_test_defs.erl

@@ -1737,7 +1737,7 @@ all_test_defs() ->
                 "for_list_preset", "for_preset", "for_records", "for_records_preset", "include",
                 "if", "if_preset", "ifequal", "ifequal_preset", "ifnotequal", "ifnotequal_preset",
                 "now", "var", "var_preset", "cycle", "custom_tag", "custom_tag1", "custom_tag2",
-                "custom_tag3", "custom_tag4", "custom_call", "include_template", "include_path",
+                "custom_tag3", "custom_tag4", "custom_tag_var", "custom_tag_lib_var", "custom_call", "include_template", "include_path",
                 "ssi", "extends_path", "extends_path2", "trans", "extends_for", "extends2",
                 "extends3", "recursive_block", "extend_recursive_block", "missing", "block_super",
                 "wrapper", "extends4", "super_escaped", "extends_chain"]
@@ -1913,6 +1913,9 @@ setup_compile("custom_tag1") -> setup_compile("custom_tag");
 setup_compile("custom_tag2") -> setup_compile("custom_tag");
 setup_compile("custom_tag3") -> setup_compile("custom_tag");
 setup_compile("custom_tag4") -> setup_compile("custom_tag");
+setup_compile("custom_tag_var") -> setup_compile("custom_tag");
+setup_compile("custom_tag_lib_var") ->
+ {ok, [[]|[{compile_opts, [{libraries, [{custom_tag_lib,erlydtl_custom_tags_lib}]}, {default_libraries, [custom_tag_lib]}]}]]};
 setup_compile("super_escaped") ->
     {ok, [[]|[{compile_opts, [auto_escape]}]]};
 setup_compile(_) ->
@@ -2028,6 +2031,10 @@ setup("custom_tag3") ->
     {ok, [{a, <<"a1">>}], [{locale, ru}], <<"b3\n">>};
 setup("custom_tag4") ->
     {ok, [], [], <<"a\n">>};
+setup("custom_tag_var") ->
+ {ok, [{a, <<"a1">>}], [{locale, ru}], <<"\nb1\n11\n">>};
+setup("custom_tag_lib_var") ->
+ {ok, [{a, <<"a1">>}], [{locale, ru}], <<"\nb1\n11\n">>};
 setup("ssi") ->
     RenderVars = [{path, "ssi_include.html"}],
     {ok, RenderVars};

+ 3 - 0
test/files/input/custom_tag_lib_var

@@ -0,0 +1,3 @@
+{% customtag2_var as tagvar %}
+{{ tagvar.name }}
+{{ tagvar.count }}

+ 3 - 0
test/files/input/custom_tag_var

@@ -0,0 +1,3 @@
+{% custom1_var as tagvar %}
+{{ tagvar.name }}
+{{ tagvar.count }}